use crate::reflection::Reflection; macro_rules! gen_struct_from_to_impls { ($struct: ident, fields=($($field: ident),*)) => { impl From> for $struct { fn from(source: winit::dpi::$struct) -> Self { Self { $($field: source.$field),* } } } impl From<$struct> for winit::dpi::$struct { fn from(source: $struct) -> Self { Self { $($field: source.$field),* } } } }; } macro_rules! gen_enum_from_to_impls { ($enum: ident, variants=($($variant: ident),*)) => { impl From for $enum { fn from(source: winit::dpi::$enum) -> Self { match source { $(winit::dpi::$enum::$variant(pos) => Self::$variant(pos.into())),* } } } impl From<$enum> for winit::dpi::$enum { fn from(source: $enum) -> Self { match source { $($enum::$variant(pos) => Self::$variant(pos.into())),* } } } }; } #[derive(Debug, Default, Clone, PartialEq, Reflection)] #[reflection(impl_with_generics(, , , ))] pub struct PhysicalPosition { pub x: Pixel, pub y: Pixel, } impl PhysicalPosition { pub fn to_logical( &self, scale_factor: f64, ) -> LogicalPosition where Pixel: Into + Clone, LogicalPixel: From, { let x = self.x.clone().into(); let y = self.y.clone().into(); LogicalPosition { x: (x / scale_factor).into(), y: (y / scale_factor).into(), } } pub fn try_convert_from( source: PhysicalPosition, ) -> Result where Pixel: TryFrom, { Ok(Self { x: source.x.try_into()?, y: source.y.try_into()?, }) } } gen_struct_from_to_impls!(PhysicalPosition, fields = (x, y)); #[derive(Debug, Default, Clone, PartialEq, Reflection)] #[reflection(impl_with_generics())] pub struct LogicalPosition { pub x: Pixel, pub y: Pixel, } impl LogicalPosition { pub fn try_convert_from( source: LogicalPosition, ) -> Result where Pixel: TryFrom, { Ok(Self { x: source.x.try_into()?, y: source.y.try_into()?, }) } } gen_struct_from_to_impls!(LogicalPosition, fields = (x, y)); #[derive(Debug, Clone, PartialEq, Reflection)] pub enum Position { Physical(PhysicalPosition), Logical(LogicalPosition), } gen_enum_from_to_impls!(Position, variants = (Physical, Logical)); #[derive(Debug, Default, Clone, PartialEq, Reflection)] #[reflection(impl_with_generics())] pub struct PhysicalSize { pub width: Pixel, pub height: Pixel, } impl PhysicalSize { pub fn to_logical(&self, scale_factor: f64) -> LogicalSize where Pixel: Into + Clone, LogicalPixel: From, { let width = self.width.clone().into(); let height = self.height.clone().into(); LogicalSize { width: (width / scale_factor).into(), height: (height / scale_factor).into(), } } } impl PhysicalSize { pub fn try_convert_from( source: PhysicalSize, ) -> Result where Pixel: TryFrom, { Ok(Self { width: source.width.try_into()?, height: source.height.try_into()?, }) } } gen_struct_from_to_impls!(PhysicalSize, fields = (width, height)); #[derive(Debug, Default, Clone, PartialEq, Reflection)] #[reflection(impl_with_generics())] pub struct LogicalSize { pub width: Pixel, pub height: Pixel, } impl LogicalSize { pub fn try_convert_from( source: LogicalSize, ) -> Result where Pixel: TryFrom, { Ok(Self { width: source.width.try_into()?, height: source.height.try_into()?, }) } } gen_struct_from_to_impls!(LogicalSize, fields = (width, height)); #[derive(Debug, Clone, PartialEq, Reflection)] pub enum Size { Physical(PhysicalSize), Logical(LogicalSize), } gen_enum_from_to_impls!(Size, variants = (Physical, Logical));