pixel_widgets/widget/
progress.rs1use crate::draw::Primitive;
2use crate::layout::{Direction, Rectangle, Size};
3use crate::node::{GenericNode, IntoNode, Node};
4use crate::style::Stylesheet;
5use crate::widget::{dummy::Dummy, Widget};
6
7pub struct Progress<'a, T> {
13 progress: f32,
14 fill: Node<'a, T>,
15}
16
17impl<'a, T: 'a> Progress<'a, T> {
18 pub fn new(progress: f32) -> Self {
20 Self {
21 progress,
22 fill: Dummy::new("bar").into_node(),
23 }
24 }
25
26 pub fn val(mut self, val: f32) -> Self {
28 self.progress = val;
29 self
30 }
31}
32
33impl<'a, T: 'a> Default for Progress<'a, T> {
34 fn default() -> Self {
35 Self {
36 progress: 0.0,
37 fill: Dummy::new("bar").into_node(),
38 }
39 }
40}
41
42impl<'a, T: 'a> Widget<'a, T> for Progress<'a, T> {
43 type State = ();
44
45 fn mount(&self) {}
46
47 fn widget(&self) -> &'static str {
48 "progress"
49 }
50
51 fn len(&self) -> usize {
52 1
53 }
54
55 fn visit_children(&mut self, visitor: &mut dyn FnMut(&mut dyn GenericNode<'a, T>)) {
56 visitor(&mut *self.fill);
57 }
58
59 fn size(&self, _: &(), style: &Stylesheet) -> (Size, Size) {
60 (style.width, style.height)
61 }
62
63 fn draw(&mut self, _: &mut (), layout: Rectangle, clip: Rectangle, style: &Stylesheet) -> Vec<Primitive<'a>> {
64 let mut result = Vec::new();
65 result.extend(style.background.render(layout));
66 let fill = layout.after_padding(style.padding);
67 let fill = match style.direction {
68 Direction::LeftToRight => Rectangle {
69 right: fill.left + fill.width() * self.progress,
70 ..fill
71 },
72 Direction::RightToLeft => Rectangle {
73 left: fill.right - fill.width() * self.progress,
74 ..fill
75 },
76 Direction::TopToBottom => Rectangle {
77 bottom: fill.top + fill.height() * self.progress,
78 ..fill
79 },
80 Direction::BottomToTop => Rectangle {
81 top: fill.bottom - fill.height() * self.progress,
82 ..fill
83 },
84 };
85
86 if self.progress > 0.0 {
87 if style.contains("clip-bar") {
88 if let Some(clip) = clip.intersect(&fill) {
89 result.push(Primitive::PushClip(clip));
90 result.extend(self.fill.draw(layout.after_padding(style.padding), clip));
91 result.push(Primitive::PopClip);
92 }
93 } else {
94 result.extend(self.fill.draw(fill, clip));
95 }
96 }
97
98 result
99 }
100}
101
102impl<'a, T: 'a> IntoNode<'a, T> for Progress<'a, T> {
103 fn into_node(self) -> Node<'a, T> {
104 Node::from_widget(self)
105 }
106}