use azul_core::{
geom::{LogicalPosition, LogicalRect, LogicalSize},
ui_solver::ResolvedOffsets,
};
use azul_css::props::{
basic::{pixel::PixelValue, PhysicalSize, PropertyContext, ResolutionContext, SizeMetric},
layout::LayoutWritingMode,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum BoxSizing {
#[default]
ContentBox,
BorderBox,
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct PositionedRectangle {
pub bounds: LogicalRect,
pub margin: ResolvedOffsets,
pub border: ResolvedOffsets,
pub padding: ResolvedOffsets,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct EdgeSizes {
pub top: f32,
pub right: f32,
pub bottom: f32,
pub left: f32,
}
impl EdgeSizes {
pub fn main_start(&self, wm: LayoutWritingMode) -> f32 {
match wm {
LayoutWritingMode::HorizontalTb => self.top,
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.left,
}
}
pub fn main_end(&self, wm: LayoutWritingMode) -> f32 {
match wm {
LayoutWritingMode::HorizontalTb => self.bottom,
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.right,
}
}
pub fn main_sum(&self, wm: LayoutWritingMode) -> f32 {
self.main_start(wm) + self.main_end(wm)
}
pub fn cross_start(&self, wm: LayoutWritingMode) -> f32 {
match wm {
LayoutWritingMode::HorizontalTb => self.left,
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.top,
}
}
pub fn cross_end(&self, wm: LayoutWritingMode) -> f32 {
match wm {
LayoutWritingMode::HorizontalTb => self.right,
LayoutWritingMode::VerticalRl | LayoutWritingMode::VerticalLr => self.bottom,
}
}
pub fn cross_sum(&self, wm: LayoutWritingMode) -> f32 {
self.cross_start(wm) + self.cross_end(wm)
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub enum UnresolvedMargin {
#[default]
Zero,
Auto,
Length(PixelValue),
}
impl UnresolvedMargin {
pub fn is_auto(&self) -> bool {
matches!(self, UnresolvedMargin::Auto)
}
pub fn resolve(&self, ctx: &ResolutionContext) -> f32 {
match self {
UnresolvedMargin::Zero => 0.0,
UnresolvedMargin::Auto => 0.0, UnresolvedMargin::Length(pv) => pv.resolve_with_context(ctx, PropertyContext::Margin),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct UnresolvedEdge<T> {
pub top: T,
pub right: T,
pub bottom: T,
pub left: T,
}
impl<T> UnresolvedEdge<T> {
pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
Self { top, right, bottom, left }
}
}
impl UnresolvedEdge<UnresolvedMargin> {
pub fn resolve(&self, ctx: &ResolutionContext) -> EdgeSizes {
EdgeSizes {
top: self.top.resolve(ctx),
right: self.right.resolve(ctx),
bottom: self.bottom.resolve(ctx),
left: self.left.resolve(ctx),
}
}
pub fn get_margin_auto(&self) -> MarginAuto {
MarginAuto {
top: self.top.is_auto(),
right: self.right.is_auto(),
bottom: self.bottom.is_auto(),
left: self.left.is_auto(),
}
}
}
impl UnresolvedEdge<PixelValue> {
pub fn resolve(&self, ctx: &ResolutionContext, prop_ctx: PropertyContext) -> EdgeSizes {
EdgeSizes {
top: self.top.resolve_with_context(ctx, prop_ctx),
right: self.right.resolve_with_context(ctx, prop_ctx),
bottom: self.bottom.resolve_with_context(ctx, prop_ctx),
left: self.left.resolve_with_context(ctx, prop_ctx),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct ResolutionParams {
pub containing_block: LogicalSize,
pub viewport_size: LogicalSize,
pub element_font_size: f32,
pub root_font_size: f32,
}
impl ResolutionParams {
pub fn to_resolution_context(&self) -> ResolutionContext {
ResolutionContext {
element_font_size: self.element_font_size,
parent_font_size: self.element_font_size, root_font_size: self.root_font_size,
element_size: None,
containing_block_size: PhysicalSize::new(
self.containing_block.width,
self.containing_block.height,
),
viewport_size: PhysicalSize::new(
self.viewport_size.width,
self.viewport_size.height,
),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct UnresolvedBoxProps {
pub margin: UnresolvedEdge<UnresolvedMargin>,
pub padding: UnresolvedEdge<PixelValue>,
pub border: UnresolvedEdge<PixelValue>,
}
impl UnresolvedBoxProps {
pub fn resolve(&self, params: &ResolutionParams) -> ResolvedBoxProps {
let ctx = params.to_resolution_context();
ResolvedBoxProps {
margin: self.margin.resolve(&ctx),
padding: self.padding.resolve(&ctx, PropertyContext::Padding),
border: self.border.resolve(&ctx, PropertyContext::BorderWidth),
margin_auto: self.margin.get_margin_auto(),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct MarginAuto {
pub left: bool,
pub right: bool,
pub top: bool,
pub bottom: bool,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ResolvedBoxProps {
pub margin: EdgeSizes,
pub padding: EdgeSizes,
pub border: EdgeSizes,
pub margin_auto: MarginAuto,
}
impl ResolvedBoxProps {
pub fn inner_size(&self, outer_size: LogicalSize, wm: LayoutWritingMode) -> LogicalSize {
let outer_main = outer_size.main(wm);
let outer_cross = outer_size.cross(wm);
let cross_axis_spacing = self.padding.cross_sum(wm) + self.border.cross_sum(wm);
let main_axis_spacing = self.padding.main_sum(wm) + self.border.main_sum(wm);
let inner_main = (outer_main - main_axis_spacing).max(0.0);
let inner_cross = (outer_cross - cross_axis_spacing).max(0.0);
LogicalSize::from_main_cross(inner_main, inner_cross, wm)
}
}
pub type BoxProps = ResolvedBoxProps;
pub use azul_css::props::layout::{LayoutClear, LayoutFloat};
#[derive(Debug, Clone, Copy, Default)]
pub struct IntrinsicSizes {
pub min_content_width: f32,
pub max_content_width: f32,
pub preferred_width: Option<f32>,
pub min_content_height: f32,
pub max_content_height: f32,
pub preferred_height: Option<f32>,
}
impl IntrinsicSizes {
pub fn zero() -> Self {
Self::default()
}
}