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
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the LICENSE-APACHE file or at:
// https://www.apache.org/licenses/LICENSE-2.0
//! Progress bar
use kas::prelude::*;
use kas::theme::Feature;
impl_scope! {
/// A progress bar
///
/// The "progress" value may range from 0.0 to 1.0.
#[autoimpl(Debug ignore self.value_fn)]
#[widget]
pub struct ProgressBar<A, D: Directional = kas::dir::Right> {
core: widget_core!(),
align: AlignPair,
direction: D,
value: f32,
value_fn: Box<dyn Fn(&ConfigCx, &A) -> f32>,
}
impl Self
where
D: Default,
{
/// Construct a slider
///
/// Closure `value_fn` returns the current progress as a value between
/// 0.0 and 1.0.
#[inline]
pub fn new(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static) -> Self {
Self::new_dir(value_fn, D::default())
}
}
impl<A> ProgressBar<A, kas::dir::Right> {
/// Construct a progress bar (horizontal)
///
/// Closure `value_fn` returns the current progress as a value between
/// 0.0 and 1.0.
#[inline]
pub fn right(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static) -> Self {
ProgressBar::new(value_fn)
}
}
impl Self {
/// Construct a slider with the given `direction`
///
/// Closure `value_fn` returns the current progress as a value between
/// 0.0 and 1.0.
#[inline]
pub fn new_dir(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static, direction: D) -> Self {
ProgressBar {
core: Default::default(),
align: Default::default(),
direction,
value: 0.0,
value_fn: Box::new(value_fn),
}
}
/// Get the progress bar's direction
#[inline]
pub fn direction(&self) -> Direction {
self.direction.as_direction()
}
}
impl Layout for Self {
fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
self.align.set_component(
axis,
match axis.is_vertical() == self.direction.is_vertical() {
false => axis.align_or_center(),
true => axis.align_or_stretch(),
},
);
sizer.feature(Feature::ProgressBar(self.direction()), axis)
}
fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect) {
let rect = cx.align_feature(Feature::ProgressBar(self.direction()), rect, self.align);
self.core.rect = rect;
}
fn draw(&mut self, mut draw: DrawCx) {
let dir = self.direction.as_direction();
draw.progress_bar(self.rect(), dir, self.value);
}
}
impl Events for Self {
type Data = A;
fn update(&mut self, cx: &mut ConfigCx, data: &A) {
let value = (self.value_fn)(cx, data);
self.value = value.clamp(0.0, 1.0);
}
}
}