• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

veeso / tui-realm-stdlib / 22147846375

18 Feb 2026 01:42PM UTC coverage: 76.863% (-0.4%) from 77.303%
22147846375

push

github

hasezoey
style(prop_ext): add module documentation

3940 of 5126 relevant lines covered (76.86%)

7.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.89
/src/components/progress_bar.rs
1
//! `ProgressBar` provides a component which shows the progress. It is possible to set the style for the progress bar and the text shown above it.
2

3
use tuirealm::command::{Cmd, CmdResult};
4
use tuirealm::props::{
5
    AttrValue, Attribute, Borders, Color, PropPayload, PropValue, Props, Style, TextModifiers,
6
    Title,
7
};
8
use tuirealm::ratatui::{layout::Rect, widgets::Gauge};
9
use tuirealm::{Frame, MockComponent, State};
10

11
use crate::prop_ext::CommonProps;
12

13
// -- Component
14

15
// TODO: we should remove this component in favor of just "LineGauge", as the implementation and inner workings are literally the same.
16

17
/// `ProgressBar` provides a component which shows the progress. It is possible to set the style for the progress bar and the text shown above it.
18
#[derive(Default)]
19
#[must_use]
20
pub struct ProgressBar {
21
    common: CommonProps,
22
    props: Props,
23
}
24

25
impl ProgressBar {
26
    /// Set the main foreground color. This may get overwritten by individual text styles.
27
    pub fn foreground(mut self, fg: Color) -> Self {
6✔
28
        self.attr(Attribute::Foreground, AttrValue::Color(fg));
6✔
29
        self
6✔
30
    }
6✔
31

32
    /// Set the main background color. This may get overwritten by individual text styles.
33
    pub fn background(mut self, bg: Color) -> Self {
6✔
34
        self.attr(Attribute::Background, AttrValue::Color(bg));
6✔
35
        self
6✔
36
    }
6✔
37

38
    /// Set the main text modifiers. This may get overwritten by individual text styles.
39
    pub fn modifiers(mut self, m: TextModifiers) -> Self {
×
40
        self.attr(Attribute::TextProps, AttrValue::TextModifiers(m));
×
41
        self
×
42
    }
×
43

44
    /// Set the main style. This may get overwritten by individual text styles.
45
    ///
46
    /// This option will overwrite any previous [`foreground`](Self::foreground), [`background`](Self::background) and [`modifiers`](Self::modifiers)!
47
    pub fn style(mut self, style: Style) -> Self {
×
48
        self.attr(Attribute::Style, AttrValue::Style(style));
×
49
        self
×
50
    }
×
51

52
    /// Set a custom style for the border when the component is unfocused.
53
    pub fn inactive(mut self, s: Style) -> Self {
×
54
        self.attr(Attribute::FocusStyle, AttrValue::Style(s));
×
55
        self
×
56
    }
×
57

58
    /// Add a border to the component.
59
    pub fn borders(mut self, b: Borders) -> Self {
3✔
60
        self.attr(Attribute::Borders, AttrValue::Borders(b));
3✔
61
        self
3✔
62
    }
3✔
63

64
    /// Add a title to the component.
65
    pub fn title<T: Into<Title>>(mut self, title: T) -> Self {
3✔
66
        self.attr(Attribute::Title, AttrValue::Title(title.into()));
3✔
67
        self
3✔
68
    }
3✔
69

70
    /// Set a label text for the Bar.
71
    pub fn label<S: Into<String>>(mut self, s: S) -> Self {
3✔
72
        self.attr(Attribute::Text, AttrValue::String(s.into()));
3✔
73
        self
3✔
74
    }
3✔
75

76
    /// Set the initial progress value.
77
    pub fn progress(mut self, p: f64) -> Self {
6✔
78
        Self::assert_progress(p);
6✔
79
        self.attr(
6✔
80
            Attribute::Value,
6✔
81
            AttrValue::Payload(PropPayload::Single(PropValue::F64(p))),
6✔
82
        );
4✔
83
        self
6✔
84
    }
6✔
85

86
    fn assert_progress(p: f64) {
9✔
87
        assert!(
9✔
88
            (0.0..=1.0).contains(&p),
9✔
89
            "Progress value must be in range [0.0, 1.0]"
2✔
90
        );
91
    }
6✔
92
}
93

94
impl MockComponent for ProgressBar {
95
    fn view(&mut self, render: &mut Frame, area: Rect) {
×
96
        if !self.common.display {
×
97
            return;
×
98
        }
×
99

100
        // Text
101
        let label = self
×
102
            .props
×
103
            .get_or(Attribute::Text, AttrValue::String(String::default()))
×
104
            .unwrap_string();
×
105
        // Get percentage
106
        let percentage = self
×
107
            .props
×
108
            .get_or(
×
109
                Attribute::Value,
×
110
                AttrValue::Payload(PropPayload::Single(PropValue::F64(0.0))),
×
111
            )
112
            .unwrap_payload()
×
113
            .unwrap_single()
×
114
            .unwrap_f64();
×
115

116
        // Make progress bar
117
        let mut widget = Gauge::default()
×
118
            .style(self.common.style)
×
119
            .gauge_style(self.common.style)
×
120
            .label(label)
×
121
            .ratio(percentage)
×
122
            .use_unicode(true);
×
123

124
        if let Some(block) = self.common.get_block() {
×
125
            widget = widget.block(block);
×
126
        }
×
127

128
        render.render_widget(widget, area);
×
129
    }
×
130

131
    fn query(&self, attr: Attribute) -> Option<AttrValue> {
×
132
        if let Some(value) = self.common.get(attr) {
×
133
            return Some(value);
×
134
        }
×
135

136
        self.props.get(attr)
×
137
    }
×
138

139
    fn attr(&mut self, attr: Attribute, value: AttrValue) {
24✔
140
        if let Some(value) = self.common.set(attr, value) {
24✔
141
            if let Attribute::Value = attr {
6✔
142
                if let AttrValue::Payload(p) = value.clone() {
3✔
143
                    Self::assert_progress(p.unwrap_single().unwrap_f64());
3✔
144
                }
3✔
145
            }
3✔
146
            self.props.set(attr, value);
6✔
147
        }
18✔
148
    }
24✔
149

150
    fn state(&self) -> State {
3✔
151
        State::None
3✔
152
    }
3✔
153

154
    fn perform(&mut self, _cmd: Cmd) -> CmdResult {
×
155
        CmdResult::None
×
156
    }
×
157
}
158

159
#[cfg(test)]
160
mod test {
161

162
    use super::*;
163

164
    use pretty_assertions::assert_eq;
165
    use tuirealm::props::HorizontalAlignment;
166

167
    #[test]
168
    fn test_components_progress_bar() {
3✔
169
        let component = ProgressBar::default()
3✔
170
            .background(Color::Red)
3✔
171
            .foreground(Color::White)
3✔
172
            .progress(0.60)
3✔
173
            .title(Title::from("Downloading file...").alignment(HorizontalAlignment::Center))
3✔
174
            .label("60% - ETA 00:20")
3✔
175
            .borders(Borders::default());
3✔
176
        // Get value
2✔
177
        assert_eq!(component.state(), State::None);
3✔
178
    }
3✔
179

180
    #[test]
181
    #[should_panic = "Progress value must be in range [0.0, 1.0]"]
182
    fn test_components_progress_bar_bad_prog() {
3✔
183
        let _ = ProgressBar::default()
3✔
184
            .background(Color::Red)
3✔
185
            .foreground(Color::White)
3✔
186
            .progress(6.0)
3✔
187
            .title(Title::from("Downloading file...").alignment(HorizontalAlignment::Center))
3✔
188
            .label("60% - ETA 00:20")
3✔
189
            .borders(Borders::default());
3✔
190
    }
3✔
191
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc