use std::{fmt, mem, sync::Arc};
use zng_app_context::context_local;
use zng_color::{colors, Hsla, Hsva, Rgba};
use zng_layout::{
    context::{LayoutMask, LAYOUT},
    unit::{
        Factor, FactorPercent, FactorSideOffsets, FactorUnits, Layout2d, Length, PxCornerRadius, PxPoint, PxRect, PxSideOffsets, PxSize,
        Size,
    },
};
use zng_var::{
    animation::{easing::EasingStep, Transitionable},
    context_var, impl_from_and_into_var, Var,
};
pub use zng_view_api::LineOrientation;
use crate::widget::VarLayout;
use super::{info::WidgetBorderInfo, WidgetId, WIDGET};
#[derive(Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum LineStyle {
    Solid,
    Double,
    Dotted,
    Dashed,
    Groove,
    Ridge,
    Wavy(f32),
    Hidden,
}
impl fmt::Debug for LineStyle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            write!(f, "LineStyle::")?;
        }
        match self {
            LineStyle::Solid => write!(f, "Solid"),
            LineStyle::Double => write!(f, "Double"),
            LineStyle::Dotted => write!(f, "Dotted"),
            LineStyle::Dashed => write!(f, "Dashed"),
            LineStyle::Groove => write!(f, "Groove"),
            LineStyle::Ridge => write!(f, "Ridge"),
            LineStyle::Wavy(t) => write!(f, "Wavy({t})"),
            LineStyle::Hidden => write!(f, "Hidden"),
        }
    }
}
impl Transitionable for LineStyle {
    fn lerp(self, to: &Self, step: EasingStep) -> Self {
        match (self, *to) {
            (Self::Wavy(a), Self::Wavy(b)) => Self::Wavy(a.lerp(&b, step)),
            (a, b) => {
                if step < 1.fct() {
                    a
                } else {
                    b
                }
            }
        }
    }
}
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
pub enum BorderStyle {
    Solid = 1,
    Double = 2,
    Dotted = 3,
    Dashed = 4,
    Hidden = 5,
    Groove = 6,
    Ridge = 7,
    Inset = 8,
    Outset = 9,
}
impl fmt::Debug for BorderStyle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            write!(f, "BorderStyle::")?;
        }
        match self {
            BorderStyle::Solid => write!(f, "Solid"),
            BorderStyle::Double => write!(f, "Double"),
            BorderStyle::Dotted => write!(f, "Dotted"),
            BorderStyle::Dashed => write!(f, "Dashed"),
            BorderStyle::Groove => write!(f, "Groove"),
            BorderStyle::Ridge => write!(f, "Ridge"),
            BorderStyle::Hidden => write!(f, "Hidden"),
            BorderStyle::Inset => write!(f, "Inset"),
            BorderStyle::Outset => write!(f, "Outset"),
        }
    }
}
impl From<BorderStyle> for zng_view_api::BorderStyle {
    fn from(s: BorderStyle) -> Self {
        match s {
            BorderStyle::Solid => zng_view_api::BorderStyle::Solid,
            BorderStyle::Double => zng_view_api::BorderStyle::Double,
            BorderStyle::Dotted => zng_view_api::BorderStyle::Dotted,
            BorderStyle::Dashed => zng_view_api::BorderStyle::Dashed,
            BorderStyle::Hidden => zng_view_api::BorderStyle::Hidden,
            BorderStyle::Groove => zng_view_api::BorderStyle::Groove,
            BorderStyle::Ridge => zng_view_api::BorderStyle::Ridge,
            BorderStyle::Inset => zng_view_api::BorderStyle::Inset,
            BorderStyle::Outset => zng_view_api::BorderStyle::Outset,
        }
    }
}
impl Transitionable for BorderStyle {
    fn lerp(self, to: &Self, step: EasingStep) -> Self {
        if step < 1.fct() {
            self
        } else {
            *to
        }
    }
}
#[repr(C)]
#[derive(Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
pub struct BorderSide {
    pub color: Rgba,
    pub style: BorderStyle,
}
impl fmt::Debug for BorderSide {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            f.debug_struct("BorderSide")
                .field("color", &self.color)
                .field("style", &self.style)
                .finish()
        } else {
            if let BorderStyle::Hidden = self.style {
                if self.color.alpha.abs() < 0.0001 {
                    return write!(f, "Hidden");
                }
            }
            write!(f, "({:?}, {:?})", self.color, self.style)
        }
    }
}
impl BorderSide {
    pub fn new<C: Into<Rgba>, S: Into<BorderStyle>>(color: C, style: S) -> Self {
        BorderSide {
            color: color.into(),
            style: style.into(),
        }
    }
    pub fn solid<C: Into<Rgba>>(color: C) -> Self {
        Self::new(color, BorderStyle::Solid)
    }
    pub fn double<C: Into<Rgba>>(color: C) -> Self {
        Self::new(color, BorderStyle::Double)
    }
    pub fn dotted<C: Into<Rgba>>(color: C) -> Self {
        Self::new(color, BorderStyle::Dotted)
    }
    pub fn dashed<C: Into<Rgba>>(color: C) -> Self {
        Self::new(color, BorderStyle::Dashed)
    }
    pub fn groove<C: Into<Rgba>>(color: C) -> Self {
        Self::new(color, BorderStyle::Groove)
    }
    pub fn ridge<C: Into<Rgba>>(color: C) -> Self {
        Self::new(color, BorderStyle::Ridge)
    }
    pub fn inset<C: Into<Rgba>>(color: C) -> Self {
        Self::new(color, BorderStyle::Inset)
    }
    pub fn outset<C: Into<Rgba>>(color: C) -> Self {
        Self::new(color, BorderStyle::Outset)
    }
    pub fn hidden() -> Self {
        Self::new(colors::BLACK.transparent(), BorderStyle::Hidden)
    }
}
impl From<BorderSide> for zng_view_api::BorderSide {
    fn from(s: BorderSide) -> Self {
        zng_view_api::BorderSide {
            color: s.color,
            style: s.style.into(),
        }
    }
}
impl Default for BorderSide {
    fn default() -> Self {
        Self::hidden()
    }
}
#[derive(Clone, Default, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
pub struct CornerRadius {
    pub top_left: Size,
    pub top_right: Size,
    pub bottom_right: Size,
    pub bottom_left: Size,
}
impl fmt::Debug for CornerRadius {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            f.debug_struct("BorderRadius")
                .field("top_left", &self.top_left)
                .field("top_right", &self.top_right)
                .field("bottom_right", &self.bottom_right)
                .field("bottom_left", &self.bottom_left)
                .finish()
        } else if self.all_corners_eq() {
            write!(f, "{:?}", self.top_left)
        } else {
            write!(
                f,
                "({:?}, {:?}, {:?}, {:?})",
                self.top_left, self.top_right, self.bottom_right, self.bottom_left
            )
        }
    }
}
impl CornerRadius {
    pub fn new<TL: Into<Size>, TR: Into<Size>, BR: Into<Size>, BL: Into<Size>>(
        top_left: TL,
        top_right: TR,
        bottom_right: BR,
        bottom_left: BL,
    ) -> Self {
        CornerRadius {
            top_left: top_left.into(),
            top_right: top_right.into(),
            bottom_right: bottom_right.into(),
            bottom_left: bottom_left.into(),
        }
    }
    pub fn new_all<E: Into<Size>>(ellipse: E) -> Self {
        let e = ellipse.into();
        CornerRadius {
            top_left: e.clone(),
            top_right: e.clone(),
            bottom_left: e.clone(),
            bottom_right: e,
        }
    }
    pub fn zero() -> Self {
        Self::new_all(Size::zero())
    }
    pub fn all_corners_eq(&self) -> bool {
        self.top_left == self.top_right && self.top_left == self.bottom_right && self.top_left == self.bottom_left
    }
}
impl Layout2d for CornerRadius {
    type Px = PxCornerRadius;
    fn layout_dft(&self, default: Self::Px) -> Self::Px {
        PxCornerRadius {
            top_left: self.top_left.layout_dft(default.top_left),
            top_right: self.top_right.layout_dft(default.top_right),
            bottom_left: self.bottom_left.layout_dft(default.bottom_left),
            bottom_right: self.bottom_right.layout_dft(default.bottom_right),
        }
    }
    fn affect_mask(&self) -> LayoutMask {
        self.top_left.affect_mask() | self.top_right.affect_mask() | self.bottom_left.affect_mask() | self.bottom_right.affect_mask()
    }
}
impl_from_and_into_var! {
    fn from(all: Size) -> CornerRadius {
        CornerRadius::new_all(all)
    }
    fn from(all: Length) -> CornerRadius {
        CornerRadius::new_all(all)
    }
    fn from(percent: FactorPercent) -> CornerRadius {
        CornerRadius::new_all(percent)
    }
   fn from(norm: Factor) -> CornerRadius {
        CornerRadius::new_all(norm)
    }
    fn from(f: f32) -> CornerRadius {
        CornerRadius::new_all(f)
    }
    fn from(i: i32) -> CornerRadius {
        CornerRadius::new_all(i)
    }
    fn from<TL: Into<Size>, TR: Into<Size>, BR: Into<Size>, BL: Into<Size>>(
        (top_left, top_right, bottom_right, bottom_left): (TL, TR, BR, BL)
    ) -> CornerRadius {
        CornerRadius::new(top_left, top_right, bottom_right, bottom_left)
    }
    fn from(corner_radius: PxCornerRadius) -> CornerRadius {
        CornerRadius::new(corner_radius.top_left, corner_radius.top_right, corner_radius.bottom_right, corner_radius.bottom_left)
    }
}
#[derive(Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize, Transitionable)]
pub struct BorderSides {
    pub left: BorderSide,
    pub right: BorderSide,
    pub top: BorderSide,
    pub bottom: BorderSide,
}
impl fmt::Debug for BorderSides {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            f.debug_struct("BorderSides")
                .field("left", &self.left)
                .field("right", &self.right)
                .field("top", &self.top)
                .field("bottom", &self.bottom)
                .finish()
        } else if self.all_eq() {
            write!(f, "{:?}", self.top)
        } else if self.dimensions_eq() {
            write!(f, "({:?}, {:?})", self.top, self.left)
        } else {
            write!(f, "({:?}, {:?}, {:?}, {:?})", self.top, self.right, self.bottom, self.left)
        }
    }
}
impl BorderSides {
    pub fn new_all<S: Into<BorderSide>>(side: S) -> Self {
        let side = side.into();
        BorderSides {
            left: side,
            right: side,
            top: side,
            bottom: side,
        }
    }
    pub fn new_vh<TB: Into<BorderSide>, LR: Into<BorderSide>>(top_bottom: TB, left_right: LR) -> Self {
        let top_bottom = top_bottom.into();
        let left_right = left_right.into();
        BorderSides {
            left: left_right,
            right: left_right,
            top: top_bottom,
            bottom: top_bottom,
        }
    }
    pub fn new<T: Into<BorderSide>, R: Into<BorderSide>, B: Into<BorderSide>, L: Into<BorderSide>>(
        top: T,
        right: R,
        bottom: B,
        left: L,
    ) -> Self {
        BorderSides {
            left: left.into(),
            right: right.into(),
            top: top.into(),
            bottom: bottom.into(),
        }
    }
    pub fn new_top<T: Into<BorderSide>>(top: T) -> Self {
        Self::new(top, BorderSide::hidden(), BorderSide::hidden(), BorderSide::hidden())
    }
    pub fn new_right<R: Into<BorderSide>>(right: R) -> Self {
        Self::new(BorderSide::hidden(), right, BorderSide::hidden(), BorderSide::hidden())
    }
    pub fn new_bottom<B: Into<BorderSide>>(bottom: B) -> Self {
        Self::new(BorderSide::hidden(), BorderSide::hidden(), bottom, BorderSide::hidden())
    }
    pub fn new_left<L: Into<BorderSide>>(left: L) -> Self {
        Self::new(BorderSide::hidden(), BorderSide::hidden(), BorderSide::hidden(), left)
    }
    pub fn solid<C: Into<Rgba>>(color: C) -> Self {
        Self::new_all(BorderSide::solid(color))
    }
    pub fn double<C: Into<Rgba>>(color: C) -> Self {
        Self::new_all(BorderSide::double(color))
    }
    pub fn dotted<C: Into<Rgba>>(color: C) -> Self {
        Self::new_all(BorderSide::dotted(color))
    }
    pub fn dashed<C: Into<Rgba>>(color: C) -> Self {
        Self::new_all(BorderSide::dashed(color))
    }
    pub fn groove<C: Into<Rgba>>(color: C) -> Self {
        Self::new_all(BorderSide::groove(color))
    }
    pub fn ridge<C: Into<Rgba>>(color: C) -> Self {
        Self::new_all(BorderSide::ridge(color))
    }
    pub fn inset<C: Into<Rgba>>(color: C) -> Self {
        Self::new_all(BorderSide::inset(color))
    }
    pub fn outset<C: Into<Rgba>>(color: C) -> Self {
        Self::new_all(BorderSide::outset(color))
    }
    pub fn hidden() -> Self {
        Self::new_all(BorderSide::hidden())
    }
    pub fn all_eq(&self) -> bool {
        self.top == self.bottom && self.top == self.left && self.top == self.right
    }
    pub fn dimensions_eq(&self) -> bool {
        self.top == self.bottom && self.left == self.right
    }
}
impl Default for BorderSides {
    fn default() -> Self {
        Self::hidden()
    }
}
impl_from_and_into_var! {
    fn from(color: Rgba) -> BorderSide {
        BorderSide::solid(color)
    }
    fn from(color: Hsva) -> BorderSide {
        BorderSide::solid(color)
    }
    fn from(color: Hsla) -> BorderSide {
        BorderSide::solid(color)
    }
    fn from(color: Rgba) -> BorderSides {
        BorderSides::new_all(color)
    }
    fn from(color: Hsva) -> BorderSides {
        BorderSides::new_all(color)
    }
    fn from(color: Hsla) -> BorderSides {
        BorderSides::new_all(color)
    }
    fn from(style: BorderStyle) -> BorderSide {
        BorderSide::new(colors::BLACK.transparent(), style)
    }
    fn from(style: BorderStyle) -> BorderSides {
        BorderSides::new_all(style)
    }
    fn from<C: Into<Rgba>, S: Into<BorderStyle>>((color, style): (C, S)) -> BorderSide {
        BorderSide::new(color, style)
    }
    fn from<C: Into<Rgba>, S: Into<BorderStyle>>((color, style): (C, S)) -> BorderSides {
        BorderSides::new_all(BorderSide::new(color, style))
    }
    fn from<T: Into<BorderSide>, R: Into<BorderSide>, B: Into<BorderSide>, L: Into<BorderSide>>(
        (top, right, bottom, left): (T, R, B, L)
    ) -> BorderSides {
        BorderSides::new(top, right, bottom, left)
    }
    fn from<TB: Into<Rgba>, LR: Into<Rgba>, S: Into<BorderStyle>>((top_bottom, left_right, style): (TB, LR, S)) -> BorderSides {
        let style = style.into();
        BorderSides::new_vh((top_bottom, style), (left_right, style))
    }
    fn from<T: Into<Rgba>, R: Into<Rgba>, B: Into<Rgba>, L: Into<Rgba>, S: Into<BorderStyle>>(
        (top, right, bottom, left, style): (T, R, B, L, S)
    ) -> BorderSides {
        let style = style.into();
        BorderSides::new(
            (top, style),
            (right, style),
            (bottom, style),
            (left, style),
        )
    }
}
#[derive(Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum CornerRadiusFit {
    None,
    Widget,
    #[default]
    Tree,
}
impl fmt::Debug for CornerRadiusFit {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            write!(f, "CornerRadiusFit::")?;
        }
        match self {
            Self::None => write!(f, "None"),
            Self::Widget => write!(f, "Widget"),
            Self::Tree => write!(f, "Tree"),
        }
    }
}
context_var! {
    pub static BORDER_ALIGN_VAR: FactorSideOffsets = FactorSideOffsets::zero();
    pub static BORDER_OVER_VAR: bool = true;
    pub static CORNER_RADIUS_VAR: CornerRadius = CornerRadius::zero();
    pub static CORNER_RADIUS_FIT_VAR: CornerRadiusFit = CornerRadiusFit::default();
}
pub struct BORDER;
impl BORDER {
    pub fn border_offsets(&self) -> PxSideOffsets {
        let data = BORDER_DATA.get();
        if data.widget_id == WIDGET.try_id() {
            data.wgt_offsets
        } else {
            PxSideOffsets::zero()
        }
    }
    pub fn inner_offsets(&self) -> PxSideOffsets {
        let data = BORDER_DATA.get();
        if data.widget_id == WIDGET.try_id() {
            data.wgt_inner_offsets
        } else {
            PxSideOffsets::zero()
        }
    }
    pub fn border_radius(&self) -> PxCornerRadius {
        match CORNER_RADIUS_FIT_VAR.get() {
            CornerRadiusFit::Tree => BORDER_DATA.get().border_radius(),
            CornerRadiusFit::Widget => {
                let data = BORDER_DATA.get();
                if data.widget_id == Some(WIDGET.id()) {
                    data.border_radius()
                } else {
                    CORNER_RADIUS_VAR.layout()
                }
            }
            _ => CORNER_RADIUS_VAR.layout(),
        }
    }
    pub fn inner_radius(&self) -> PxCornerRadius {
        match CORNER_RADIUS_FIT_VAR.get() {
            CornerRadiusFit::Tree => BORDER_DATA.get().inner_radius(),
            CornerRadiusFit::Widget => {
                let data = BORDER_DATA.get();
                if data.widget_id == WIDGET.try_id() {
                    data.inner_radius()
                } else {
                    CORNER_RADIUS_VAR.layout()
                }
            }
            _ => CORNER_RADIUS_VAR.layout(),
        }
    }
    pub fn outer_radius(&self) -> PxCornerRadius {
        BORDER_DATA.get().corner_radius
    }
    pub fn fill_bounds(&self) -> (PxRect, PxCornerRadius) {
        let align = BORDER_ALIGN_VAR.get();
        let fill_size = LAYOUT.constraints().fill_size();
        let inner_offsets = self.inner_offsets();
        if align == FactorSideOffsets::zero() {
            let fill_size = PxSize::new(
                fill_size.width + inner_offsets.horizontal(),
                fill_size.height + inner_offsets.vertical(),
            );
            return (PxRect::from_size(fill_size), self.outer_radius());
        } else if align == FactorSideOffsets::new_all(1.0.fct()) {
            return (
                PxRect::new(PxPoint::new(inner_offsets.left, inner_offsets.top), fill_size),
                self.inner_radius(),
            );
        }
        let outer = self.outer_radius();
        let inner = self.inner_radius();
        let b_align = FactorSideOffsets {
            top: 1.0.fct() - align.top,
            right: 1.0.fct() - align.right,
            bottom: 1.0.fct() - align.bottom,
            left: 1.0.fct() - align.left,
        };
        let bounds = PxRect {
            origin: PxPoint::new(inner_offsets.left * (align.left), inner_offsets.top * align.top),
            size: PxSize::new(
                fill_size.width + inner_offsets.left * b_align.left + inner_offsets.right * b_align.right,
                fill_size.height + inner_offsets.top * b_align.top + inner_offsets.bottom * b_align.bottom,
            ),
        };
        let radius = PxCornerRadius {
            top_left: PxSize::new(
                outer.top_left.width.lerp(&inner.top_left.width, align.left),
                outer.top_left.height.lerp(&inner.top_left.height, align.top),
            ),
            top_right: PxSize::new(
                outer.top_right.width.lerp(&inner.top_right.width, align.right),
                outer.top_right.height.lerp(&inner.top_right.height, align.top),
            ),
            bottom_left: PxSize::new(
                outer.bottom_left.width.lerp(&inner.bottom_left.width, align.left),
                outer.bottom_left.height.lerp(&inner.bottom_left.height, align.bottom),
            ),
            bottom_right: PxSize::new(
                outer.bottom_right.width.lerp(&inner.bottom_right.width, align.right),
                outer.bottom_right.height.lerp(&inner.bottom_right.height, align.bottom),
            ),
        };
        (bounds, radius)
    }
    pub(super) fn with_inner(&self, f: impl FnOnce() -> PxSize) -> PxSize {
        let mut data = BORDER_DATA.get_clone();
        let border = WIDGET.border();
        data.add_inner(&border);
        BORDER_DATA.with_context(&mut Some(Arc::new(data)), || {
            let corner_radius = BORDER.border_radius();
            border.set_corner_radius(corner_radius);
            border.set_offsets(PxSideOffsets::zero());
            f()
        })
    }
    pub fn measure_border(&self, offsets: PxSideOffsets, f: impl FnOnce() -> PxSize) -> PxSize {
        let mut data = BORDER_DATA.get_clone();
        data.add_offset(None, offsets);
        BORDER_DATA.with_context(&mut Some(Arc::new(data)), f)
    }
    pub fn layout_border(&self, offsets: PxSideOffsets, f: impl FnOnce()) {
        let mut data = BORDER_DATA.get_clone();
        data.add_offset(Some(&WIDGET.border()), offsets);
        BORDER_DATA.with_context(&mut Some(Arc::new(data)), f);
    }
    pub fn with_corner_radius<R>(&self, f: impl FnOnce() -> R) -> R {
        let mut data = BORDER_DATA.get_clone();
        data.set_corner_radius();
        BORDER_DATA.with_context(&mut Some(Arc::new(data)), f)
    }
    pub fn border_layout(&self) -> (PxRect, PxSideOffsets) {
        BORDER_LAYOUT.get().unwrap_or_else(|| {
            #[cfg(debug_assertions)]
            tracing::error!("the `border_layout` is only available inside the layout and render methods of the border visual node");
            (PxRect::zero(), PxSideOffsets::zero())
        })
    }
    pub fn with_border_layout(&self, rect: PxRect, offsets: PxSideOffsets, f: impl FnOnce()) {
        BORDER_LAYOUT.with_context(&mut Some(Arc::new(Some((rect, offsets)))), f)
    }
}
context_local! {
    static BORDER_DATA: BorderOffsetsData = BorderOffsetsData::default();
    static BORDER_LAYOUT: Option<(PxRect, PxSideOffsets)> = None;
}
#[derive(Debug, Clone, Default)]
struct BorderOffsetsData {
    widget_id: Option<WidgetId>,
    wgt_offsets: PxSideOffsets,
    wgt_inner_offsets: PxSideOffsets,
    eval_cr: bool,
    corner_radius: PxCornerRadius,
    cr_offsets: PxSideOffsets,
    cr_inner_offsets: PxSideOffsets,
}
impl BorderOffsetsData {
    fn add_offset(&mut self, layout_info: Option<&WidgetBorderInfo>, offset: PxSideOffsets) {
        let widget_id = Some(WIDGET.id());
        let is_wgt_start = self.widget_id != widget_id;
        if is_wgt_start {
            self.widget_id = widget_id;
            self.wgt_offsets = PxSideOffsets::zero();
            self.wgt_inner_offsets = PxSideOffsets::zero();
            self.eval_cr |= layout_info.is_some() && matches!(CORNER_RADIUS_FIT_VAR.get(), CornerRadiusFit::Widget);
        }
        self.wgt_offsets = self.wgt_inner_offsets;
        self.wgt_inner_offsets += offset;
        if mem::take(&mut self.eval_cr) {
            self.corner_radius = CORNER_RADIUS_VAR.layout();
            self.cr_offsets = PxSideOffsets::zero();
            self.cr_inner_offsets = PxSideOffsets::zero();
        }
        self.cr_offsets = self.cr_inner_offsets;
        self.cr_inner_offsets += offset;
        if let Some(border) = layout_info {
            if is_wgt_start {
                border.set_corner_radius(self.corner_radius);
            }
            border.set_offsets(self.wgt_inner_offsets);
        }
    }
    fn add_inner(&mut self, layout_info: &WidgetBorderInfo) {
        self.add_offset(Some(layout_info), PxSideOffsets::zero());
    }
    fn set_corner_radius(&mut self) {
        self.eval_cr = matches!(CORNER_RADIUS_FIT_VAR.get(), CornerRadiusFit::Tree);
    }
    fn border_radius(&self) -> PxCornerRadius {
        self.corner_radius.deflate(self.cr_offsets)
    }
    fn inner_radius(&self) -> PxCornerRadius {
        self.corner_radius.deflate(self.cr_inner_offsets)
    }
}