pub use crate::drag::{DragDelta, OptionDragDelta};
#[derive(Copy, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(C)]
pub struct LogicalRect {
pub origin: LogicalPosition,
pub size: LogicalSize,
}
impl core::fmt::Debug for LogicalRect {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{} @ {}", self.size, self.origin)
}
}
impl core::fmt::Display for LogicalRect {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{} @ {}", self.size, self.origin)
}
}
impl LogicalRect {
pub const fn zero() -> Self {
Self::new(LogicalPosition::zero(), LogicalSize::zero())
}
pub const fn new(origin: LogicalPosition, size: LogicalSize) -> Self {
Self { origin, size }
}
#[inline]
pub fn scale_for_dpi(&mut self, scale_factor: f32) {
self.origin.x *= scale_factor;
self.origin.y *= scale_factor;
self.size.width *= scale_factor;
self.size.height *= scale_factor;
}
#[inline(always)]
pub fn max_x(&self) -> f32 {
self.origin.x + self.size.width
}
#[inline(always)]
pub fn min_x(&self) -> f32 {
self.origin.x
}
#[inline(always)]
pub fn max_y(&self) -> f32 {
self.origin.y + self.size.height
}
#[inline(always)]
pub fn min_y(&self) -> f32 {
self.origin.y
}
#[inline]
pub fn intersects(&self, other: Self) -> bool {
if self.max_x() <= other.min_x() || other.max_x() <= self.min_x() {
return false;
}
if self.max_y() <= other.min_y() || other.max_y() <= self.min_y() {
return false;
}
true
}
#[inline]
pub fn contains(&self, point: LogicalPosition) -> bool {
point.x >= self.min_x()
&& point.x < self.max_x()
&& point.y >= self.min_y()
&& point.y < self.max_y()
}
#[inline]
pub fn hit_test(&self, other: &LogicalPosition) -> Option<LogicalPosition> {
let dx_left_edge = other.x - self.min_x();
let dx_right_edge = self.max_x() - other.x;
let dy_top_edge = other.y - self.min_y();
let dy_bottom_edge = self.max_y() - other.y;
if dx_left_edge > 0.0 && dx_right_edge > 0.0 && dy_top_edge > 0.0 && dy_bottom_edge > 0.0 {
Some(LogicalPosition::new(dx_left_edge, dy_top_edge))
} else {
None
}
}
}
impl_vec!(LogicalRect, LogicalRectVec, LogicalRectVecDestructor, LogicalRectVecDestructorType, LogicalRectVecSlice, OptionLogicalRect);
impl_vec_clone!(LogicalRect, LogicalRectVec, LogicalRectVecDestructor);
impl_vec_debug!(LogicalRect, LogicalRectVec);
impl_vec_partialeq!(LogicalRect, LogicalRectVec);
impl_vec_partialord!(LogicalRect, LogicalRectVec);
impl_vec_ord!(LogicalRect, LogicalRectVec);
impl_vec_hash!(LogicalRect, LogicalRectVec);
impl_vec_eq!(LogicalRect, LogicalRectVec);
use core::{
cmp::Ordering,
hash::{Hash, Hasher},
ops::{self, AddAssign, SubAssign},
};
use azul_css::props::layout::LayoutWritingMode;
#[derive(Default, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct LogicalPosition {
pub x: f32,
pub y: f32,
}
impl LogicalPosition {
pub fn scale_for_dpi(&mut self, scale_factor: f32) {
self.x *= scale_factor;
self.y *= scale_factor;
}
}
impl SubAssign<LogicalPosition> for LogicalPosition {
fn sub_assign(&mut self, other: LogicalPosition) {
self.x -= other.x;
self.y -= other.y;
}
}
impl AddAssign<LogicalPosition> for LogicalPosition {
fn add_assign(&mut self, other: LogicalPosition) {
self.x += other.x;
self.y += other.y;
}
}
impl core::fmt::Debug for LogicalPosition {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl core::fmt::Display for LogicalPosition {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl ops::Add for LogicalPosition {
type Output = Self;
#[inline]
fn add(self, other: Self) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl ops::Sub for LogicalPosition {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self {
Self {
x: self.x - other.x,
y: self.y - other.y,
}
}
}
const DECIMAL_MULTIPLIER: f32 = 1000.0;
impl_option!(
LogicalPosition,
OptionLogicalPosition,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
impl Ord for LogicalPosition {
fn cmp(&self, other: &LogicalPosition) -> Ordering {
let self_x = (self.x * DECIMAL_MULTIPLIER) as isize;
let self_y = (self.y * DECIMAL_MULTIPLIER) as isize;
let other_x = (other.x * DECIMAL_MULTIPLIER) as isize;
let other_y = (other.y * DECIMAL_MULTIPLIER) as isize;
self_x.cmp(&other_x).then(self_y.cmp(&other_y))
}
}
impl Eq for LogicalPosition {}
impl Hash for LogicalPosition {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
let self_x = (self.x * DECIMAL_MULTIPLIER) as isize;
let self_y = (self.y * DECIMAL_MULTIPLIER) as isize;
self_x.hash(state);
self_y.hash(state);
}
}
impl LogicalPosition {
pub fn main(&self, wm: LayoutWritingMode) -> f32 {
match wm {
LayoutWritingMode::HorizontalTb => self.y,
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.x,
}
}
pub fn cross(&self, wm: LayoutWritingMode) -> f32 {
match wm {
LayoutWritingMode::HorizontalTb => self.x,
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.y,
}
}
pub fn from_main_cross(main: f32, cross: f32, wm: LayoutWritingMode) -> Self {
match wm {
LayoutWritingMode::HorizontalTb => Self::new(cross, main),
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => Self::new(main, cross),
}
}
}
#[derive(Default, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct LogicalSize {
pub width: f32,
pub height: f32,
}
impl LogicalSize {
pub fn scale_for_dpi(&mut self, scale_factor: f32) -> Self {
self.width *= scale_factor;
self.height *= scale_factor;
*self
}
pub fn from_main_cross(main: f32, cross: f32, wm: LayoutWritingMode) -> Self {
match wm {
LayoutWritingMode::HorizontalTb => Self::new(cross, main),
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => Self::new(main, cross),
}
}
}
impl core::fmt::Debug for LogicalSize {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}x{}", self.width, self.height)
}
}
impl core::fmt::Display for LogicalSize {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}x{}", self.width, self.height)
}
}
impl_option!(
LogicalSize,
OptionLogicalSize,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
impl_option!(
LogicalRect,
OptionLogicalRect,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
impl Ord for LogicalSize {
fn cmp(&self, other: &LogicalSize) -> Ordering {
let self_width = (self.width * DECIMAL_MULTIPLIER) as isize;
let self_height = (self.height * DECIMAL_MULTIPLIER) as isize;
let other_width = (other.width * DECIMAL_MULTIPLIER) as isize;
let other_height = (other.height * DECIMAL_MULTIPLIER) as isize;
self_width
.cmp(&other_width)
.then(self_height.cmp(&other_height))
}
}
impl Eq for LogicalSize {}
impl Hash for LogicalSize {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
let self_width = (self.width * DECIMAL_MULTIPLIER) as isize;
let self_height = (self.height * DECIMAL_MULTIPLIER) as isize;
self_width.hash(state);
self_height.hash(state);
}
}
impl LogicalSize {
pub fn main(&self, wm: LayoutWritingMode) -> f32 {
match wm {
LayoutWritingMode::HorizontalTb => self.height,
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.width,
}
}
pub fn cross(&self, wm: LayoutWritingMode) -> f32 {
match wm {
LayoutWritingMode::HorizontalTb => self.width,
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.height,
}
}
pub fn with_main(self, wm: LayoutWritingMode, value: f32) -> Self {
match wm {
LayoutWritingMode::HorizontalTb => Self {
height: value,
..self
},
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => Self {
width: value,
..self
},
}
}
pub fn with_cross(self, wm: LayoutWritingMode, value: f32) -> Self {
match wm {
LayoutWritingMode::HorizontalTb => Self {
width: value,
..self
},
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => Self {
height: value,
..self
},
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct PhysicalPosition<T> {
pub x: T,
pub y: T,
}
impl<T: ::core::fmt::Display> ::core::fmt::Debug for PhysicalPosition<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
pub type PhysicalPositionI32 = PhysicalPosition<i32>;
impl_option!(
PhysicalPositionI32,
OptionPhysicalPositionI32,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
#[derive(Ord, Hash, Eq, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct PhysicalSize<T> {
pub width: T,
pub height: T,
}
impl<T: ::core::fmt::Display> ::core::fmt::Debug for PhysicalSize<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{}x{}", self.width, self.height)
}
}
pub type PhysicalSizeU32 = PhysicalSize<u32>;
impl_option!(
PhysicalSizeU32,
OptionPhysicalSizeU32,
[Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
);
pub type PhysicalSizeF32 = PhysicalSize<f32>;
impl_option!(
PhysicalSizeF32,
OptionPhysicalSizeF32,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
impl LogicalPosition {
#[inline(always)]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
#[inline(always)]
pub const fn zero() -> Self {
Self::new(0.0, 0.0)
}
#[inline(always)]
pub fn to_physical(self, hidpi_factor: f32) -> PhysicalPosition<u32> {
PhysicalPosition {
x: libm::roundf(self.x * hidpi_factor) as u32,
y: libm::roundf(self.y * hidpi_factor) as u32,
}
}
}
impl<T> PhysicalPosition<T> {
#[inline(always)]
pub const fn new(x: T, y: T) -> Self {
Self { x, y }
}
}
impl PhysicalPosition<i32> {
#[inline(always)]
pub const fn zero() -> Self {
Self::new(0, 0)
}
#[inline(always)]
pub fn to_logical(self, hidpi_factor: f32) -> LogicalPosition {
LogicalPosition {
x: self.x as f32 / hidpi_factor,
y: self.y as f32 / hidpi_factor,
}
}
}
impl PhysicalPosition<f64> {
#[inline(always)]
pub const fn zero() -> Self {
Self::new(0.0, 0.0)
}
#[inline(always)]
pub fn to_logical(self, hidpi_factor: f32) -> LogicalPosition {
LogicalPosition {
x: self.x as f32 / hidpi_factor,
y: self.y as f32 / hidpi_factor,
}
}
}
impl LogicalSize {
#[inline(always)]
pub const fn new(width: f32, height: f32) -> Self {
Self { width, height }
}
#[inline(always)]
pub const fn zero() -> Self {
Self::new(0.0, 0.0)
}
#[inline(always)]
pub fn to_physical(self, hidpi_factor: f32) -> PhysicalSize<u32> {
PhysicalSize {
width: libm::roundf(self.width * hidpi_factor) as u32,
height: libm::roundf(self.height * hidpi_factor) as u32,
}
}
}
impl<T> PhysicalSize<T> {
#[inline(always)]
pub const fn new(width: T, height: T) -> Self {
Self { width, height }
}
}
impl PhysicalSize<u32> {
#[inline(always)]
pub const fn zero() -> Self {
Self::new(0, 0)
}
#[inline(always)]
pub fn to_logical(self, hidpi_factor: f32) -> LogicalSize {
LogicalSize {
width: self.width as f32 / hidpi_factor,
height: self.height as f32 / hidpi_factor,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum CoordinateSpace {
Window,
ScrollFrame,
Parent,
ReferenceFrame,
}
#[derive(Default, Debug, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct ScreenPosition {
pub x: f32,
pub y: f32,
}
impl ScreenPosition {
#[inline(always)]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
#[inline(always)]
pub const fn zero() -> Self {
Self::new(0.0, 0.0)
}
#[inline(always)]
pub const fn to_logical(self) -> LogicalPosition {
LogicalPosition { x: self.x, y: self.y }
}
#[inline(always)]
pub const fn from_logical(p: LogicalPosition) -> Self {
Self { x: p.x, y: p.y }
}
}
impl_option!(
ScreenPosition,
OptionScreenPosition,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);
#[derive(Default, Debug, Copy, Clone, PartialEq, PartialOrd)]
#[repr(C)]
pub struct CursorNodePosition {
pub x: f32,
pub y: f32,
}
impl CursorNodePosition {
#[inline(always)]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
#[inline(always)]
pub const fn zero() -> Self {
Self::new(0.0, 0.0)
}
#[inline(always)]
pub const fn to_logical(self) -> LogicalPosition {
LogicalPosition { x: self.x, y: self.y }
}
#[inline(always)]
pub const fn from_logical(p: LogicalPosition) -> Self {
Self { x: p.x, y: p.y }
}
}
impl_option!(
CursorNodePosition,
OptionCursorNodePosition,
[Debug, Copy, Clone, PartialEq, PartialOrd]
);