use std::fmt::{Display, Formatter};
use std::mem;
use std::sync::atomic::{AtomicIsize, Ordering};
static UNIQUE_ID: AtomicIsize = AtomicIsize::new(1);
pub(crate) fn get_unique_id() -> isize {
UNIQUE_ID.fetch_add(1, Ordering::Relaxed)
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Dimension {
id: isize,
pub(crate) width: i32,
pub(crate) height: i32,
pub(crate) padding: i32,
}
impl Dimension {
pub fn new(width: i32, height: i32) -> Self {
Self::with_id(get_unique_id(), width, height, 0)
}
pub fn with_padding(width: i32, height: i32, padding: i32) -> Self {
Self::with_id(get_unique_id(), width, height, padding)
}
pub fn with_id(id: isize, width: i32, height: i32, padding: i32) -> Self {
Self {
id,
width: width.max(0),
height: height.max(0),
padding: padding.max(0),
}
}
pub fn id(&self) -> isize {
self.id
}
pub fn width(&self) -> i32 {
self.width
}
pub(crate) fn width_total(&self) -> i32 {
self.width + (self.padding << 1)
}
pub fn height(&self) -> i32 {
self.height
}
pub(crate) fn height_total(&self) -> i32 {
self.height + (self.padding << 1)
}
pub fn padding(&self) -> i32 {
self.padding
}
pub fn set_id(&mut self, value: isize) {
self.id = value;
}
pub fn set_width(&mut self, value: i32) {
self.width = value.max(0);
}
pub fn set_height(&mut self, value: i32) {
self.height = value.max(0);
}
pub fn set_dimension(&mut self, width: i32, height: i32) {
self.width = width;
self.height = height;
}
pub fn set_padding(&mut self, value: i32) {
self.padding = value.max(0);
}
pub fn flip(&mut self) {
mem::swap(&mut self.width, &mut self.height);
}
pub fn to_flipped(&self) -> Self {
Self::with_id(self.id, self.height, self.width, self.padding)
}
pub fn is_empty(&self) -> bool {
self.width == 0 || self.height == 0
}
pub(crate) fn is_empty_total(&self) -> bool {
(self.width + self.padding) == 0 || (self.height + self.padding) == 0
}
pub fn area(&self) -> i64 {
self.width as i64 * self.height as i64
}
pub(crate) fn area_total(&self) -> i64 {
self.width_total() as i64 * self.height_total() as i64
}
}
impl Default for Dimension {
fn default() -> Self {
Dimension::new(0, 0)
}
}
impl Display for Dimension {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Dimension(id: {}, width: {}, height: {}, padding: {})",
self.id, self.width, self.height, self.padding
)
}
}
#[cfg(test)]
mod tests;