1
1
Fork 0
mirror of https://github.com/griffi-gh/hUI.git synced 2025-03-14 03:46:27 -05:00
hUI/hui/src/element/builtin/image.rs
2024-03-07 02:40:11 +01:00

103 lines
3 KiB
Rust

use derive_setters::Setters;
use glam::vec2;
use crate::{
background::BackgroundColor,
draw::{ImageHandle, RoundedCorners, UiDrawCommand},
element::{MeasureContext, ProcessContext, UiElement},
layout::{Size, Size2d},
measure::Response,
rectangle::Corners,
};
#[derive(Setters)]
#[setters(prefix = "with_")]
pub struct Image {
/// Image handle to draw
#[setters(skip)]
pub image: ImageHandle,
/// Size of the image.
///
/// - If one of the dimensions is `Size::Auto`, the image will be scaled to fit the other dimension\
/// (aspect ratio is preserved)
/// - If both dimensions are `Size::Auto`, the image will be drawn at its original size
/// - All other values behave as expected
#[setters(into)]
pub size: Size2d,
/// Color of the image
///
/// Image will get multiplied/tinted by this color or gradient
#[setters(into)]
pub color: BackgroundColor,
/// Corner radius of the image
#[setters(into)]
pub corner_radius: Corners<f32>,
}
impl Image {
pub fn new(handle: ImageHandle) -> Self {
Self {
image: handle,
size: Size2d {
width: Size::Auto,
height: Size::Auto,
},
color: BackgroundColor::from((1., 1., 1., 1.)),
corner_radius: Corners::all(0.),
}
}
}
impl UiElement for Image {
fn name(&self) -> &'static str {
"Image"
}
fn measure(&self, ctx: MeasureContext) -> Response {
let dim = ctx.images.get_size(self.image).expect("invalid image handle");
Response {
size: vec2(
match self.size.width {
Size::Auto => {
match self.size.height {
Size::Auto => dim.x as f32,
Size::Fraction(f) => ((f * ctx.layout.max_size.y) / dim.y as f32) * dim.x as f32,
Size::Static(pixels) => (pixels / dim.y as f32) * dim.x as f32,
}
},
Size::Fraction(percentage) => ctx.layout.max_size.x * percentage,
Size::Static(pixels) => pixels,
},
match self.size.height {
Size::Auto => {
match self.size.width {
Size::Auto => dim.y as f32,
Size::Fraction(f) => ((f * ctx.layout.max_size.x) / dim.x as f32) * dim.y as f32,
Size::Static(pixels) => (pixels / dim.x as f32) * dim.y as f32,
}
},
Size::Fraction(percentage) => ctx.layout.max_size.y * percentage,
Size::Static(pixels) => pixels,
},
),
..Default::default()
}
}
fn process(&self, ctx: ProcessContext) {
if !self.color.is_transparent() {
ctx.draw.add(UiDrawCommand::Rectangle {
position: ctx.layout.position,
size: ctx.measure.size,
color: self.color.corners(),
texture: Some(self.image),
rounded_corners: (self.corner_radius.max_f32() > 0.).then_some({
RoundedCorners::from_radius(self.corner_radius)
}),
});
}
}
}