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
use crate::draw::Primitive;
use crate::layout::{Direction, Rectangle, Size};
use crate::node::{GenericNode, IntoNode, Node};
use crate::style::Stylesheet;
use crate::widget::{dummy::Dummy, Widget};
pub struct Progress<'a, T> {
    progress: f32,
    fill: Node<'a, T>,
}
impl<'a, T: 'a> Progress<'a, T> {
    
    pub fn new(progress: f32) -> Self {
        Self {
            progress,
            fill: Dummy::new("bar").into_node(),
        }
    }
    
    pub fn val(mut self, val: f32) -> Self {
        self.progress = val;
        self
    }
}
impl<'a, T: 'a> Default for Progress<'a, T> {
    fn default() -> Self {
        Self {
            progress: 0.0,
            fill: Dummy::new("bar").into_node(),
        }
    }
}
impl<'a, T: 'a> Widget<'a, T> for Progress<'a, T> {
    type State = ();
    fn mount(&self) {}
    fn widget(&self) -> &'static str {
        "progress"
    }
    fn len(&self) -> usize {
        1
    }
    fn visit_children(&mut self, visitor: &mut dyn FnMut(&mut dyn GenericNode<'a, T>)) {
        visitor(&mut *self.fill);
    }
    fn size(&self, _: &(), style: &Stylesheet) -> (Size, Size) {
        (style.width, style.height)
    }
    fn draw(&mut self, _: &mut (), layout: Rectangle, clip: Rectangle, style: &Stylesheet) -> Vec<Primitive<'a>> {
        let mut result = Vec::new();
        result.extend(style.background.render(layout));
        let fill = layout.after_padding(style.padding);
        let fill = match style.direction {
            Direction::LeftToRight => Rectangle {
                right: fill.left + fill.width() * self.progress,
                ..fill
            },
            Direction::RightToLeft => Rectangle {
                left: fill.right - fill.width() * self.progress,
                ..fill
            },
            Direction::TopToBottom => Rectangle {
                bottom: fill.top + fill.height() * self.progress,
                ..fill
            },
            Direction::BottomToTop => Rectangle {
                top: fill.bottom - fill.height() * self.progress,
                ..fill
            },
        };
        if self.progress > 0.0 {
            if style.contains("clip-bar") {
                if let Some(clip) = clip.intersect(&fill) {
                    result.push(Primitive::PushClip(clip));
                    result.extend(self.fill.draw(layout.after_padding(style.padding), clip));
                    result.push(Primitive::PopClip);
                }
            } else {
                result.extend(self.fill.draw(fill, clip));
            }
        }
        result
    }
}
impl<'a, T: 'a> IntoNode<'a, T> for Progress<'a, T> {
    fn into_node(self) -> Node<'a, T> {
        Node::from_widget(self)
    }
}