use frames for progressbar

This commit is contained in:
griffi-gh 2024-03-25 16:16:56 +01:00
parent b87a0b2f04
commit 9f3d2c7def
3 changed files with 71 additions and 51 deletions

View file

@ -62,7 +62,7 @@ fn main() {
children: ElementList(vec![
Box::new(ProgressBar {
value: z,
corner_radius: Corners::all(0.25 * ProgressBar::DEFAULT_HEIGHT),
// corner_radius: Corners::all(0.25 * ProgressBar::DEFAULT_HEIGHT),
..Default::default()
}),
Box::new(Container {

View file

@ -1,6 +1,6 @@
use std::time::Instant;
use hui::{
element::{
color, element::{
container::Container,
progress_bar::ProgressBar,
text::Text,
@ -43,7 +43,14 @@ ui_main!{
.add_child(ui);
ProgressBar::default()
.with_value(mom_ratio)
.with_corner_radius(0.125 * ProgressBar::DEFAULT_HEIGHT)
.with_background(frame_rect! {
color: color::BLACK,
corner_radius: 0.125 * ProgressBar::DEFAULT_HEIGHT
})
.with_foreground(frame_rect! {
color: color::BLUE,
corner_radius: 0.125 * ProgressBar::DEFAULT_HEIGHT
})
.add_child(ui);
Container::default()
.with_direction(Direction::Horizontal)

View file

@ -1,16 +1,15 @@
use derive_setters::Setters;
use glam::{vec2, vec4};
use glam::vec2;
use crate::{
draw::{RoundedCorners, UiDrawCommand},
element::{MeasureContext, ProcessContext, UiElement},
frame::{Frame, FrameRect},
layout::{compute_size, Size, Size2d},
measure::Response,
rect::{Corners, FillColor}
};
//TODO: Use Frames here instead of FillColor
#[derive(Debug, Clone, Copy, Setters)]
#[derive(Setters)]
#[setters(prefix = "with_")]
pub struct ProgressBar {
/// Current progress, should be in the range 0.0..=1.0
@ -21,20 +20,26 @@ pub struct ProgressBar {
pub size: Size2d,
/// Foreground (bar) color
#[setters(into)]
pub foreground: FillColor,
#[setters(skip)]
pub foreground: Box<dyn Frame>,
/// Background color
#[setters(into)]
pub background: FillColor,
/// Corner radius of the progress bar
#[setters(into)]
pub corner_radius: Corners<f32>,
#[setters(skip)]
pub background: Box<dyn Frame>,
}
impl ProgressBar {
pub const DEFAULT_HEIGHT: f32 = 20.0;
pub fn with_background(mut self, frame: impl Frame + 'static) -> Self {
self.background = Box::new(frame);
self
}
pub fn with_foreground(mut self, frame: impl Frame + 'static) -> Self {
self.foreground = Box::new(frame);
self
}
}
impl Default for ProgressBar {
@ -42,9 +47,8 @@ impl Default for ProgressBar {
Self {
value: 0.,
size: Size::Auto.into(),
foreground: vec4(0.0, 0.0, 1.0, 1.0).into(),
background: vec4(0.0, 0.0, 0.0, 1.0).into(),
corner_radius: Corners::all(0.),
foreground: Box::new(FrameRect::color((0.0, 0.0, 1.0, 1.0))),
background: Box::new(FrameRect::color((0.0, 0.0, 0.0, 1.0))),
}
}
}
@ -57,7 +61,7 @@ impl UiElement for ProgressBar {
fn measure(&self, ctx: MeasureContext) -> Response {
Response {
size: compute_size(ctx.layout, self.size, vec2(
ctx.layout.max_size.x.max(300.),
ctx.layout.max_size.x.max(300.), //XXX: remove .max(300)?
Self::DEFAULT_HEIGHT,
)),
hints: Default::default(),
@ -68,40 +72,49 @@ impl UiElement for ProgressBar {
fn process(&self, ctx: ProcessContext) {
let value = self.value.clamp(0., 1.);
let rounded_corners =
(self.corner_radius.max_f32() > 0.).then_some({
//HACK: fix clipping issues; //todo: get rid of this
let mut radii = self.corner_radius;
let width = ctx.measure.size.x * value;
if width <= radii.max_f32() * 2. {
radii.bottom_right = 0.;
radii.top_right = 0.;
}
if width <= radii.max_f32() {
radii.bottom_left = 0.;
radii.top_left = 0.;
}
RoundedCorners::from_radius(radii)
});
if value < 1. {
ctx.draw.add(UiDrawCommand::Rectangle {
position: ctx.layout.position,
size: ctx.measure.size,
color: self.background.corners(),
texture: None,
texture_uv: None,
rounded_corners
});
//FIXME: these optimizations may not be valid
if value < 1. || !self.foreground.covers_opaque() {
self.background.draw(ctx.draw, ctx.layout.position, ctx.measure.size);
}
if value > 0. {
ctx.draw.add(UiDrawCommand::Rectangle {
position: ctx.layout.position,
size: ctx.measure.size * vec2(value, 1.0),
color: self.foreground.corners(),
texture: None,
texture_uv: None,
rounded_corners,
});
self.foreground.draw(ctx.draw, ctx.layout.position, ctx.measure.size * vec2(value, 1.));
}
// let rounded_corners =
// (self.corner_radius.max_f32() > 0.).then_some({
// //HACK: fix clipping issues; //todo: get rid of this
// let mut radii = self.corner_radius;
// let width = ctx.measure.size.x * value;
// if width <= radii.max_f32() * 2. {
// radii.bottom_right = 0.;
// radii.top_right = 0.;
// }
// if width <= radii.max_f32() {
// radii.bottom_left = 0.;
// radii.top_left = 0.;
// }
// RoundedCorners::from_radius(radii)
// });
// if value < 1. {
// ctx.draw.add(UiDrawCommand::Rectangle {
// position: ctx.layout.position,
// size: ctx.measure.size,
// color: self.background.corners(),
// texture: None,
// texture_uv: None,
// rounded_corners
// });
// }
// if value > 0. {
// ctx.draw.add(UiDrawCommand::Rectangle {
// position: ctx.layout.position,
// size: ctx.measure.size * vec2(value, 1.0),
// color: self.foreground.corners(),
// texture: None,
// texture_uv: None,
// rounded_corners,
// });
// }
}
}