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![ children: ElementList(vec![
Box::new(ProgressBar { Box::new(ProgressBar {
value: z, value: z,
corner_radius: Corners::all(0.25 * ProgressBar::DEFAULT_HEIGHT), // corner_radius: Corners::all(0.25 * ProgressBar::DEFAULT_HEIGHT),
..Default::default() ..Default::default()
}), }),
Box::new(Container { Box::new(Container {

View file

@ -1,6 +1,6 @@
use std::time::Instant; use std::time::Instant;
use hui::{ use hui::{
element::{ color, element::{
container::Container, container::Container,
progress_bar::ProgressBar, progress_bar::ProgressBar,
text::Text, text::Text,
@ -43,7 +43,14 @@ ui_main!{
.add_child(ui); .add_child(ui);
ProgressBar::default() ProgressBar::default()
.with_value(mom_ratio) .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); .add_child(ui);
Container::default() Container::default()
.with_direction(Direction::Horizontal) .with_direction(Direction::Horizontal)

View file

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