1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use crate::prelude::*;

/// A simple ProgressBar that can be used to show progress of something.
///
/// the input lens need to be a [f32] with range of `0.0..1.0`
///
/// # Example
///
/// ### Vertical ProgressBar bound to the input lens
/// ```
/// # use vizia_core::prelude::*;
/// # use vizia_derive::*;
/// # let mut cx = &mut Context::default();
/// # #[derive(Lens, Default)]
/// # pub struct AppData {
/// #     progress: f32,
/// # }
/// # impl Model for AppData {}
/// # AppData::default().build(cx);
/// ProgressBar::vertical(cx, AppData::progress);
/// ```
///
/// ### Horizontal ProgressBar bound to the input lens
/// ```
/// # use vizia_core::prelude::*;
/// # use vizia_derive::*;
/// # let mut cx = &mut Context::default();
/// # #[derive(Lens, Default)]
/// # pub struct AppData {
/// #     progress: f32,
/// # }
/// # impl Model for AppData {}
/// # AppData::default().build(cx);
/// ProgressBar::horizontal(cx, AppData::progress);
/// ```
///
/// ### A Horizontal ProgressBar with a label beside it to show the progress
/// ```
/// # use vizia_core::prelude::*;
/// # use vizia_derive::*;
/// # let mut cx = &mut Context::default();
/// # #[derive(Lens, Default)]
/// # pub struct AppData {
/// #     progress: f32,
/// # }
/// # impl Model for AppData {}
/// # AppData::default().build(cx);
/// HStack::new(cx, |cx| {
///     ProgressBar::horizontal(cx, AppData::progress);
///     Label::new(cx, AppData::progress.map(|v| format!("{:.0}%", v * 100.0)));
/// });
/// ```
///
/// ### A Horizontal ProgressBar with dynamic bar background color using a lens
/// we can dynamically change the background color of the bar using `bar_color` method on Handle
/// ```
/// # use vizia_core::prelude::*;
/// # use vizia_derive::*;
/// # let mut cx = &mut Context::default();
/// # #[derive(Lens, Default)]
/// # pub struct AppData {
/// #     progress: f32,
/// #     color: Color,
/// # }
/// # impl Model for AppData {}
/// # AppData::default().build(cx);
/// ProgressBar::horizontal(cx, AppData::progress).bar_color(AppData::color);
/// ```
pub struct ProgressBar;

impl View for ProgressBar {
    fn element(&self) -> Option<&'static str> {
        Some("progressbar")
    }
}

impl ProgressBar {
    /// Creates a new progress bar bound to the value targeted by the lens.
    ///
    /// # Example
    ///
    /// ```
    /// # use vizia_core::prelude::*;
    /// # use vizia_derive::*;
    /// # let mut cx = &mut Context::default();
    /// # #[derive(Lens, Default)]
    /// # pub struct AppData {
    /// #     value: f32,
    /// # }
    /// # impl Model for AppData {}
    /// # AppData::default().build(cx);
    /// ProgressBar::new(cx, AppData::value, Orientation::Horizontal);
    /// ```
    pub fn new<L>(cx: &mut Context, lens: L, orientation: Orientation) -> Handle<Self>
    where
        L: Lens<Target = f32>,
    {
        match orientation {
            Orientation::Horizontal => Self::horizontal(cx, lens),
            Orientation::Vertical => Self::vertical(cx, lens),
        }
    }

    /// Creates a new horizontal progress bar bound to the value targeted by the lens.
    pub fn horizontal<L>(cx: &mut Context, lens: L) -> Handle<Self>
    where
        L: Lens<Target = f32>,
    {
        Self.build(cx, |cx| {
            let progress = lens.map(|v| Units::Percentage(v * 100.0));
            Element::new(cx).width(progress).class("progressbar-bar");
        })
    }

    /// Creates a new vertical progress bar bound to the value targeted by the lens.
    pub fn vertical<L>(cx: &mut Context, lens: L) -> Handle<Self>
    where
        L: Lens<Target = f32>,
    {
        Self.build(cx, |cx| {
            let progress = lens.map(|v| Units::Percentage(v * 100.0));
            Element::new(cx).top(Stretch(1.0)).height(progress).class("progressbar-bar");
        })
    }
}

impl<'a> Handle<'a, ProgressBar> {
    /// Set the color of the bar inside the ProgressBar.
    ///
    /// you also pass a lens to this method if you want to be able to change the color
    /// dynamically.
    pub fn bar_color(self, color: impl Res<Color>) -> Self {
        self.bind(color, |mut h, c| {
            let first_child = h.entity.first_child(&h.cx.tree).unwrap();
            h.entity = first_child;
            let val = c.get(&h);
            h.background_color(val);
        })
    }
}