use taffy::{AvailableSpace, Size};
pub const DEFAULT_FONT_SIZE: f32 = 16.0;
pub const DEFAULT_DEVICE_PIXEL_RATIO: f32 = 1.0;
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct Viewport {
pub size: ViewportSize,
pub font_size: f32,
pub device_pixel_ratio: f32,
}
impl From<Viewport> for Size<AvailableSpace> {
fn from(value: Viewport) -> Self {
Self {
width: if let Some(width) = value.size.width {
AvailableSpace::Definite(width as f32)
} else {
AvailableSpace::MaxContent
},
height: if let Some(height) = value.size.height {
AvailableSpace::Definite(height as f32)
} else {
AvailableSpace::MaxContent
},
}
}
}
impl Default for Viewport {
fn default() -> Self {
Self::new((None, None))
}
}
impl Viewport {
pub fn new(size: impl Into<ViewportSize>) -> Self {
Self {
size: size.into(),
font_size: DEFAULT_FONT_SIZE,
device_pixel_ratio: DEFAULT_DEVICE_PIXEL_RATIO,
}
}
pub const fn with_font_size(mut self, font_size: f32) -> Self {
self.font_size = font_size;
self
}
pub const fn with_device_pixel_ratio(mut self, device_pixel_ratio: f32) -> Self {
self.device_pixel_ratio = device_pixel_ratio;
self
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ViewportSize {
pub width: Option<u32>,
pub height: Option<u32>,
}
impl From<(u32, u32)> for ViewportSize {
fn from(value: (u32, u32)) -> Self {
Self {
width: Some(value.0),
height: Some(value.1),
}
}
}
impl From<(Option<u32>, u32)> for ViewportSize {
fn from(value: (Option<u32>, u32)) -> Self {
Self {
width: value.0,
height: Some(value.1),
}
}
}
impl From<(u32, Option<u32>)> for ViewportSize {
fn from(value: (u32, Option<u32>)) -> Self {
Self {
width: Some(value.0),
height: value.1,
}
}
}
impl From<(Option<u32>, Option<u32>)> for ViewportSize {
fn from(value: (Option<u32>, Option<u32>)) -> Self {
Self {
width: value.0,
height: value.1,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_viewport_new_defaults() {
let v = Viewport::new((800, 600));
assert_eq!(v.size.width, Some(800));
assert_eq!(v.size.height, Some(600));
assert_eq!(v.font_size, DEFAULT_FONT_SIZE);
}
}