use crate::geometry::Size;
#[derive(Copy, Clone, Debug, PartialEq, Default)]
pub struct Insets {
pub left: f64,
pub right: f64,
pub top: f64,
pub bottom: f64,
}
impl Insets {
pub const ZERO: Self = Self { left: 0.0, right: 0.0, top: 0.0, bottom: 0.0 };
pub fn all(v: f64) -> Self {
Self { left: v, right: v, top: v, bottom: v }
}
pub fn symmetric(h: f64, v: f64) -> Self {
Self { left: h, right: h, top: v, bottom: v }
}
pub fn from_sides(left: f64, right: f64, top: f64, bottom: f64) -> Self {
Self { left, right, top, bottom }
}
#[inline] pub fn horizontal(&self) -> f64 { self.left + self.right }
#[inline] pub fn vertical(&self) -> f64 { self.top + self.bottom }
#[inline]
pub fn scale(self, factor: f64) -> Self {
Self {
left: self.left * factor,
right: self.right * factor,
top: self.top * factor,
bottom: self.bottom * factor,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct HAnchor(u8);
impl HAnchor {
pub const ABSOLUTE: Self = HAnchor(0);
pub const LEFT: Self = HAnchor(1);
pub const CENTER: Self = HAnchor(2);
pub const RIGHT: Self = HAnchor(4);
pub const FIT: Self = HAnchor(8);
pub const STRETCH: Self = HAnchor(5); pub const MAX_FIT_OR_STRETCH: Self = HAnchor(13); pub const MIN_FIT_OR_STRETCH: Self = HAnchor(16);
#[inline]
pub fn contains(self, flags: Self) -> bool {
flags.0 != 0 && (self.0 & flags.0) == flags.0
}
#[inline]
pub fn is_stretch(self) -> bool {
self.contains(Self::LEFT) && self.contains(Self::RIGHT)
}
}
impl Default for HAnchor {
fn default() -> Self { Self::FIT }
}
impl std::ops::BitOr for HAnchor {
type Output = Self;
fn bitor(self, rhs: Self) -> Self { HAnchor(self.0 | rhs.0) }
}
impl std::ops::BitAnd for HAnchor {
type Output = Self;
fn bitand(self, rhs: Self) -> Self { HAnchor(self.0 & rhs.0) }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct VAnchor(u8);
impl VAnchor {
pub const ABSOLUTE: Self = VAnchor(0);
pub const BOTTOM: Self = VAnchor(1);
pub const CENTER: Self = VAnchor(2);
pub const TOP: Self = VAnchor(4);
pub const FIT: Self = VAnchor(8);
pub const STRETCH: Self = VAnchor(5); pub const MAX_FIT_OR_STRETCH: Self = VAnchor(13); pub const MIN_FIT_OR_STRETCH: Self = VAnchor(16);
#[inline]
pub fn contains(self, flags: Self) -> bool {
flags.0 != 0 && (self.0 & flags.0) == flags.0
}
#[inline]
pub fn is_stretch(self) -> bool {
self.contains(Self::BOTTOM) && self.contains(Self::TOP)
}
}
impl Default for VAnchor {
fn default() -> Self { Self::FIT }
}
impl std::ops::BitOr for VAnchor {
type Output = Self;
fn bitor(self, rhs: Self) -> Self { VAnchor(self.0 | rhs.0) }
}
impl std::ops::BitAnd for VAnchor {
type Output = Self;
fn bitand(self, rhs: Self) -> Self { VAnchor(self.0 & rhs.0) }
}
#[derive(Copy, Clone, Debug)]
pub struct WidgetBase {
pub margin: Insets,
pub h_anchor: HAnchor,
pub v_anchor: VAnchor,
pub min_size: Size,
pub max_size: Size,
pub enforce_integer_bounds: bool,
}
impl WidgetBase {
pub fn new() -> Self {
Self {
margin: Insets::ZERO,
h_anchor: HAnchor::FIT,
v_anchor: VAnchor::FIT,
min_size: Size::ZERO,
max_size: Size::MAX,
enforce_integer_bounds: crate::pixel_bounds::default_enforce_integer_bounds(),
}
}
pub fn with_margin(mut self, m: Insets) -> Self { self.margin = m; self }
pub fn with_h_anchor(mut self, h: HAnchor) -> Self { self.h_anchor = h; self }
pub fn with_v_anchor(mut self, v: VAnchor) -> Self { self.v_anchor = v; self }
pub fn with_min_size(mut self, s: Size) -> Self { self.min_size = s; self }
pub fn with_max_size(mut self, s: Size) -> Self { self.max_size = s; self }
#[inline]
pub fn clamp_size(&self, proposed: Size) -> Size {
Size::new(
proposed.width .clamp(self.min_size.width, self.max_size.width),
proposed.height.clamp(self.min_size.height, self.max_size.height),
)
}
pub fn scaled_margin(&self) -> Insets {
self.margin
}
}
impl Default for WidgetBase {
fn default() -> Self { Self::new() }
}
#[inline]
pub fn resolve_fit_or_stretch(fit_size: f64, stretch_size: f64, max_mode: bool) -> f64 {
if max_mode {
fit_size.max(stretch_size)
} else {
fit_size.min(stretch_size)
}
}