#[allow(clippy::wildcard_imports)] // widget/render module pulls in the css property/value types it builds with
fn build_button_container_style(button_type: ButtonType) -> Vec<CssPropertyWithConditions> {
CssPropertyWithConditions::simple(CssProperty::const_padding_top(LayoutPaddingTop::const_px(6))),
CssPropertyWithConditions::simple(CssProperty::const_padding_bottom(LayoutPaddingBottom::const_px(6))),
props.push(CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::InlineFlex)));
props.push(CssPropertyWithConditions::simple(CssProperty::const_flex_direction(LayoutFlexDirection::Row)));
props.push(CssPropertyWithConditions::simple(CssProperty::const_justify_content(LayoutJustifyContent::Center)));
props.push(CssPropertyWithConditions::simple(CssProperty::const_align_items(LayoutAlignItems::Center)));
props.push(CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_text_color(StyleTextColor { inner: text_color })));
props.push(CssPropertyWithConditions::simple(CssProperty::const_padding_top(LayoutPaddingTop::const_px(6))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_padding_bottom(LayoutPaddingBottom::const_px(6))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_padding_left(LayoutPaddingLeft::const_px(12))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_padding_right(LayoutPaddingRight::const_px(12))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_top_left_radius(StyleBorderTopLeftRadius::const_px(4))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_top_right_radius(StyleBorderTopRightRadius::const_px(4))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_bottom_left_radius(StyleBorderBottomLeftRadius::const_px(4))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_bottom_right_radius(StyleBorderBottomRightRadius::const_px(4))));
StyleBackgroundContentVec::from_const_slice(&[StyleBackgroundContent::Color(ColorU::TRANSPARENT)]),
props.push(CssPropertyWithConditions::on_hover(CssProperty::TextDecoration(StyleTextDecoration::Underline.into())));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_top_width(LayoutBorderTopWidth::const_px(1))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_bottom_width(LayoutBorderBottomWidth::const_px(1))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_left_width(LayoutBorderLeftWidth::const_px(1))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_right_width(LayoutBorderRightWidth::const_px(1))));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_top_style(StyleBorderTopStyle { inner: BorderStyle::Solid })));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_bottom_style(StyleBorderBottomStyle { inner: BorderStyle::Solid })));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_left_style(StyleBorderLeftStyle { inner: BorderStyle::Solid })));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_right_style(StyleBorderRightStyle { inner: BorderStyle::Solid })));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_top_color(StyleBorderTopColor { inner: border_color })));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_bottom_color(StyleBorderBottomColor { inner: border_color })));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_left_color(StyleBorderLeftColor { inner: border_color })));
props.push(CssPropertyWithConditions::simple(CssProperty::const_border_right_color(StyleBorderRightColor { inner: border_color })));
props.push(CssPropertyWithConditions::on_hover(CssProperty::BorderTopColor(StyleBorderTopColor { inner: hover_border }.into())));
props.push(CssPropertyWithConditions::on_hover(CssProperty::BorderBottomColor(StyleBorderBottomColor { inner: hover_border }.into())));
props.push(CssPropertyWithConditions::on_hover(CssProperty::BorderLeftColor(StyleBorderLeftColor { inner: hover_border }.into())));
props.push(CssPropertyWithConditions::on_hover(CssProperty::BorderRightColor(StyleBorderRightColor { inner: hover_border }.into())));
props.push(CssPropertyWithConditions::on_focus(CssProperty::BorderTopColor(StyleBorderTopColor { inner: focus_outline_color }.into())));
props.push(CssPropertyWithConditions::on_focus(CssProperty::BorderBottomColor(StyleBorderBottomColor { inner: focus_outline_color }.into())));
props.push(CssPropertyWithConditions::on_focus(CssProperty::BorderLeftColor(StyleBorderLeftColor { inner: focus_outline_color }.into())));
props.push(CssPropertyWithConditions::on_focus(CssProperty::BorderRightColor(StyleBorderRightColor { inner: focus_outline_color }.into())));
CssPropertyWithConditions::simple(CssProperty::const_font_size(StyleFontSize::const_px(14))),
self.container_style = CssPropertyWithConditionsVec::from_vec(build_button_container_style(button_type));
.with_children(azul_core::dom::DomVec::from_vec(vec![Dom::create_text_do_not_use_without_block_level_wrapper(self.label)])),
assert_eq!(pv.metric, SizeMetric::Px, "button geometry must be absolute px, got {:?}", pv.metric);
let find = |f: &dyn Fn(&CssProperty) -> Option<f32>| v.as_ref().iter().find_map(|p| f(&p.property));
assert_eq!(get_button_colors(ty), get_button_colors(ty), "{ty:?}: colours are not deterministic");
assert_eq!((normal, hover, active), (TRANSPARENT, TRANSPARENT, TRANSPARENT), "Link must paint nothing");
assert!(seen.insert((normal.r, normal.g, normal.b, normal.a)), "{ty:?}: duplicate background {normal:?}");
assert_eq!(get_button_text_color(ty) != WHITE, is_special, "{ty:?}: text colour contradicts the documented variant");
assert!(separation >= 85.0, "{ty:?}: text {text:?} on {bg:?} is unreadable (luma separation {separation:.1})");
assert!(separation >= alt_separation, "{ty:?}: {alt:?} would be more readable than {text:?} on {bg:?}");
assert_eq!(top, bottom, "{ty:?}: vertical padding is asymmetric — the label will not be centred");
let baseline = properties(&CssPropertyWithConditionsVec::from_vec(build_button_container_style(ButtonType::Default)));
assert_eq!(properties(&v), baseline, "{ty:?}: container style diverged — was the bisection probe reverted?");
assert_eq!(user_select, Some(StyleUserSelect::None), "a button label must not be text-selectable");
assert!(v.as_ref().iter().all(|p| p.apply_if.as_ref().is_empty()), "label style must be unconditional");
assert_eq!(build_button_label_style(), build_button_label_style(), "label style is not deterministic");
assert_eq!(a, b, "create() diverged from with_type(_, Default) for a {}-byte label", label.len());
assert_eq!(b.container_style.len(), container.len(), "{ty:?}: container_style length is inconsistent");
assert_eq!(b.container_style.as_ref(), container.as_slice(), "{ty:?}: container_style does not match the builder");
assert_eq!(b.label_style.as_ref(), label_style.as_slice(), "{ty:?}: label_style does not match the builder");
assert_eq!(b.image_style.as_ref(), b.label_style.as_ref(), "{ty:?}: image_style diverged from label_style");
assert_eq!(format!("{b:?}"), format!("{c:?}"), "{ty:?}: Debug output diverged between clones");
assert_eq!(b.container_style.len(), len, "container_style grew across repeated set_button_type calls");
assert_eq!(b, Button::create(AzString::from("")), "swap_with_default left a non-default button");
assert_eq!(dom.children.as_ref().len(), 2, "{w}x{h}: expected an image child and a label child");
assert_eq!(dom.root.callbacks.as_ref().len(), 1, "a re-set callback was appended instead of replaced");
let dom = btn("Click", ButtonType::Success).with_on_click(RefAny::new(0xDEAD_BEEF_u32), cb).dom();
assert_eq!(callbacks[0].callback.cb, expected_ptr, "the fn pointer was corrupted on the way into the DOM");
assert_eq!(*data.downcast_ref::<u32>().expect("payload changed type"), 0xDEAD_BEEF, "payload was corrupted");
assert!(data.downcast_ref::<u64>().is_none(), "downcast to the wrong type must fail, not reinterpret");
assert_eq!(callbacks[0].callback.cb, expected_ptr, "the Callback -> ButtonOnClickCallback transmute mangled the pointer");
assert!(matches!(dom.root.get_node_type(), NodeType::Button), "{ty:?}: root is not a Button node");
assert_eq!(inline_properties(&dom), container, "{ty:?}: the root inline style is not the container style");
assert_eq!(children.len(), 1, "{ty:?}: an image-less button is a Button node with exactly one <p> label child");
assert_eq!(inline_properties(&children[0]), label_style, "{ty:?}: the label style is not on the label node");
assert!(matches!(children[0].root.get_node_type(), NodeType::Image(_)), "the image must come first (left of the label)");
assert_eq!(inline_properties(&children[0]), image_style, "the image style is not on the image node");
assert_eq!(dom.estimated_total_children, count_descendants(&dom), "{ty:?}: stale estimated_total_children");
assert_eq!(dom.estimated_total_children, 2, "{ty:?}: an image-less button has the <p> label and its text node");
assert_eq!(a.children.as_ref().len(), b.children.as_ref().len(), "{ty:?}: child count differs");