#[cfg(not(feature = "std"))]
use alloc::string::ToString;
use alloc::{boxed::Box, collections::btree_map::BTreeMap, string::String, vec::Vec};
use core::{
fmt,
hash::{Hash, Hasher},
iter::FromIterator,
mem,
sync::atomic::{AtomicUsize, Ordering},
};
use azul_css::{
css::{BoxOrStatic, Css, NodeTypeTag},
format_rust_code::GetHash,
props::{
basic::{FloatValue, FontRef},
layout::{LayoutDisplay, LayoutFloat, LayoutPosition},
property::CssProperty,
},
AzString, OptionString,
};
pub use crate::a11y::*;
pub use crate::events::{
ApplicationEventFilter, ComponentEventFilter, EventFilter, FocusEventFilter, HoverEventFilter,
WindowEventFilter,
};
pub use crate::id::{Node, NodeHierarchy, NodeId};
use crate::{
callbacks::{
CoreCallback, CoreCallbackData, CoreCallbackDataVec, CoreCallbackType, VirtualViewCallback,
VirtualViewCallbackType,
},
geom::LogicalPosition,
id::{NodeDataContainer, NodeDataContainerRef, NodeDataContainerRefMut},
menu::Menu,
prop_cache::{CssPropertyCache, CssPropertyCachePtr},
refany::{OptionRefAny, RefAny},
resources::{
image_ref_get_hash, CoreImageCallback, ImageMask, ImageRef, ImageRefHash, RendererResources,
},
styled_dom::{
CompactDom, NodeHierarchyItemId, StyleFontFamilyHash, StyledDom, StyledNode,
StyledNodeState,
},
window::OptionVirtualKeyCodeCombo,
};
pub use azul_css::dynamic_selector::{CssPropertyWithConditions, CssPropertyWithConditionsVec};
static TAG_ID: AtomicUsize = AtomicUsize::new(1);
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum InputType {
Text,
Button,
Checkbox,
Color,
Date,
Datetime,
DatetimeLocal,
Email,
File,
Hidden,
Image,
Month,
Number,
Password,
Radio,
Range,
Reset,
Search,
Submit,
Tel,
Time,
Url,
Week,
}
impl InputType {
pub const fn as_str(&self) -> &'static str {
match self {
InputType::Text => "text",
InputType::Button => "button",
InputType::Checkbox => "checkbox",
InputType::Color => "color",
InputType::Date => "date",
InputType::Datetime => "datetime",
InputType::DatetimeLocal => "datetime-local",
InputType::Email => "email",
InputType::File => "file",
InputType::Hidden => "hidden",
InputType::Image => "image",
InputType::Month => "month",
InputType::Number => "number",
InputType::Password => "password",
InputType::Radio => "radio",
InputType::Range => "range",
InputType::Reset => "reset",
InputType::Search => "search",
InputType::Submit => "submit",
InputType::Tel => "tel",
InputType::Time => "time",
InputType::Url => "url",
InputType::Week => "week",
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub struct TagId {
pub inner: u64,
}
impl ::core::fmt::Display for TagId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TagId").field("inner", &self.inner).finish()
}
}
impl_option!(
TagId,
OptionTagId,
[Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash]
);
impl TagId {
pub const fn into_crate_internal(&self) -> TagId {
TagId { inner: self.inner }
}
pub const fn from_crate_internal(t: TagId) -> Self {
TagId { inner: t.inner }
}
pub fn unique() -> Self {
loop {
let current = TAG_ID.load(Ordering::SeqCst);
let next = if current == usize::MAX { 1 } else { current + 1 };
if TAG_ID.compare_exchange(current, next, Ordering::SeqCst, Ordering::SeqCst).is_ok() {
return TagId { inner: current as u64 };
}
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[repr(C)]
pub struct ScrollTagId {
pub inner: TagId,
}
impl ::core::fmt::Display for ScrollTagId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ScrollTagId")
.field("inner", &self.inner)
.finish()
}
}
impl ::core::fmt::Debug for ScrollTagId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl ScrollTagId {
pub fn unique() -> ScrollTagId {
ScrollTagId {
inner: TagId::unique(),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub enum ScrollbarOrientation {
Horizontal,
Vertical,
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
#[repr(C)]
pub struct DomNodeHash {
pub inner: u64,
}
impl ::core::fmt::Debug for DomNodeHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DomNodeHash({})", self.inner)
}
}
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
#[repr(C, u8)]
pub enum NodeType {
Html,
Head,
Body,
Div,
P,
Article,
Section,
Nav,
Aside,
Header,
Footer,
Main,
Figure,
FigCaption,
H1,
H2,
H3,
H4,
H5,
H6,
Br,
Hr,
Pre,
BlockQuote,
Address,
Details,
Summary,
Dialog,
Ul,
Ol,
Li,
Dl,
Dt,
Dd,
Menu,
MenuItem,
Dir,
Table,
Caption,
THead,
TBody,
TFoot,
Tr,
Th,
Td,
ColGroup,
Col,
Form,
FieldSet,
Legend,
Label,
Input,
Button,
Select,
OptGroup,
SelectOption,
TextArea,
Output,
Progress,
Meter,
DataList,
Span,
A,
Em,
Strong,
B,
I,
U,
S,
Mark,
Del,
Ins,
Code,
Samp,
Kbd,
Var,
Cite,
Dfn,
Abbr,
Acronym,
Q,
Time,
Sub,
Sup,
Small,
Big,
Bdo,
Bdi,
Wbr,
Ruby,
Rt,
Rtc,
Rp,
Data,
Canvas,
Object,
Param,
Embed,
Audio,
Video,
Source,
Track,
Map,
Area,
Svg,
SvgG,
SvgDefs,
SvgSymbol,
SvgUse,
SvgSwitch,
SvgPath,
SvgCircle,
SvgRect,
SvgEllipse,
SvgLine,
SvgPolygon,
SvgPolyline,
SvgText(AzString),
SvgTspan,
SvgTextPath,
SvgLinearGradient,
SvgRadialGradient,
SvgStop,
SvgPattern,
SvgClipPathElement,
SvgMask,
SvgFilter,
SvgFeBlend,
SvgFeColorMatrix,
SvgFeComponentTransfer,
SvgFeComposite,
SvgFeConvolveMatrix,
SvgFeDiffuseLighting,
SvgFeDisplacementMap,
SvgFeDistantLight,
SvgFeDropShadow,
SvgFeFlood,
SvgFeFuncR,
SvgFeFuncG,
SvgFeFuncB,
SvgFeFuncA,
SvgFeGaussianBlur,
SvgFeImage,
SvgFeMerge,
SvgFeMergeNode,
SvgFeMorphology,
SvgFeOffset,
SvgFePointLight,
SvgFeSpecularLighting,
SvgFeSpotLight,
SvgFeTile,
SvgFeTurbulence,
SvgMarker,
SvgImage(ImageRef),
SvgForeignObject,
SvgTitle,
SvgDesc,
SvgMetadata,
SvgA,
SvgView,
SvgStyle,
SvgScript,
SvgAnimate,
SvgAnimateMotion,
SvgAnimateTransform,
SvgSet,
SvgMpath,
Title,
Meta,
Link,
Script,
Style,
Base,
Before,
After,
Marker,
Placeholder,
Text(BoxOrStatic<AzString>),
Image(BoxOrStatic<ImageRef>),
VirtualView,
Icon(BoxOrStatic<AzString>),
GeolocationProbe(crate::geolocation::GeolocationProbeConfig),
}
pub type BoxOrStaticImageRef = BoxOrStatic<ImageRef>;
impl_option!(NodeType, OptionNodeType, copy = false, [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]);
impl NodeType {
fn into_library_owned_nodetype(&self) -> Self {
use self::NodeType::*;
match self {
Html => Html,
Head => Head,
Body => Body,
Div => Div,
P => P,
Article => Article,
Section => Section,
Nav => Nav,
Aside => Aside,
Header => Header,
Footer => Footer,
Main => Main,
Figure => Figure,
FigCaption => FigCaption,
H1 => H1,
H2 => H2,
H3 => H3,
H4 => H4,
H5 => H5,
H6 => H6,
Br => Br,
Hr => Hr,
Pre => Pre,
BlockQuote => BlockQuote,
Address => Address,
Details => Details,
Summary => Summary,
Dialog => Dialog,
Ul => Ul,
Ol => Ol,
Li => Li,
Dl => Dl,
Dt => Dt,
Dd => Dd,
Menu => Menu,
MenuItem => MenuItem,
Dir => Dir,
Table => Table,
Caption => Caption,
THead => THead,
TBody => TBody,
TFoot => TFoot,
Tr => Tr,
Th => Th,
Td => Td,
ColGroup => ColGroup,
Col => Col,
Form => Form,
FieldSet => FieldSet,
Legend => Legend,
Label => Label,
Input => Input,
Button => Button,
Select => Select,
OptGroup => OptGroup,
SelectOption => SelectOption,
TextArea => TextArea,
Output => Output,
Progress => Progress,
Meter => Meter,
DataList => DataList,
Span => Span,
A => A,
Em => Em,
Strong => Strong,
B => B,
I => I,
U => U,
S => S,
Mark => Mark,
Del => Del,
Ins => Ins,
Code => Code,
Samp => Samp,
Kbd => Kbd,
Var => Var,
Cite => Cite,
Dfn => Dfn,
Abbr => Abbr,
Acronym => Acronym,
Q => Q,
Time => Time,
Sub => Sub,
Sup => Sup,
Small => Small,
Big => Big,
Bdo => Bdo,
Bdi => Bdi,
Wbr => Wbr,
Ruby => Ruby,
Rt => Rt,
Rtc => Rtc,
Rp => Rp,
Data => Data,
Canvas => Canvas,
Object => Object,
Param => Param,
Embed => Embed,
Audio => Audio,
Video => Video,
Source => Source,
Track => Track,
Map => Map,
Area => Area,
Svg => Svg, SvgG => SvgG, SvgDefs => SvgDefs, SvgSymbol => SvgSymbol,
SvgUse => SvgUse, SvgSwitch => SvgSwitch,
SvgPath => SvgPath, SvgCircle => SvgCircle, SvgRect => SvgRect,
SvgEllipse => SvgEllipse, SvgLine => SvgLine,
SvgPolygon => SvgPolygon, SvgPolyline => SvgPolyline,
SvgText(s) => SvgText(s.clone_self()),
SvgTspan => SvgTspan, SvgTextPath => SvgTextPath,
SvgLinearGradient => SvgLinearGradient, SvgRadialGradient => SvgRadialGradient,
SvgStop => SvgStop, SvgPattern => SvgPattern,
SvgClipPathElement => SvgClipPathElement, SvgMask => SvgMask,
SvgFilter => SvgFilter, SvgFeBlend => SvgFeBlend,
SvgFeColorMatrix => SvgFeColorMatrix,
SvgFeComponentTransfer => SvgFeComponentTransfer,
SvgFeComposite => SvgFeComposite, SvgFeConvolveMatrix => SvgFeConvolveMatrix,
SvgFeDiffuseLighting => SvgFeDiffuseLighting,
SvgFeDisplacementMap => SvgFeDisplacementMap,
SvgFeDistantLight => SvgFeDistantLight, SvgFeDropShadow => SvgFeDropShadow,
SvgFeFlood => SvgFeFlood,
SvgFeFuncR => SvgFeFuncR, SvgFeFuncG => SvgFeFuncG,
SvgFeFuncB => SvgFeFuncB, SvgFeFuncA => SvgFeFuncA,
SvgFeGaussianBlur => SvgFeGaussianBlur, SvgFeImage => SvgFeImage,
SvgFeMerge => SvgFeMerge, SvgFeMergeNode => SvgFeMergeNode,
SvgFeMorphology => SvgFeMorphology, SvgFeOffset => SvgFeOffset,
SvgFePointLight => SvgFePointLight,
SvgFeSpecularLighting => SvgFeSpecularLighting,
SvgFeSpotLight => SvgFeSpotLight,
SvgFeTile => SvgFeTile, SvgFeTurbulence => SvgFeTurbulence,
SvgMarker => SvgMarker,
SvgImage(i) => SvgImage(i.clone()),
SvgForeignObject => SvgForeignObject,
SvgTitle => SvgTitle, SvgDesc => SvgDesc, SvgMetadata => SvgMetadata,
SvgA => SvgA, SvgView => SvgView,
SvgStyle => SvgStyle, SvgScript => SvgScript,
SvgAnimate => SvgAnimate, SvgAnimateMotion => SvgAnimateMotion,
SvgAnimateTransform => SvgAnimateTransform,
SvgSet => SvgSet, SvgMpath => SvgMpath,
Title => Title,
Meta => Meta,
Link => Link,
Script => Script,
Style => Style,
Base => Base,
Before => Before,
After => After,
Marker => Marker,
Placeholder => Placeholder,
Text(s) => Text(BoxOrStatic::heap(s.clone_self())),
Image(i) => Image(i.clone()),
VirtualView => VirtualView,
Icon(s) => Icon(BoxOrStatic::heap(s.clone_self())),
GeolocationProbe(cfg) => GeolocationProbe(*cfg),
}
}
pub fn format(&self) -> Option<String> {
use self::NodeType::*;
match self {
Text(s) => Some(format!("{}", s)),
Image(id) => Some(format!("image({:?})", id)),
VirtualView => Some("virtualized-view".to_string()),
Icon(s) => Some(format!("icon({})", s)),
GeolocationProbe(cfg) => Some(format!(
"geolocation-probe(hi={}, bg={}, max={}m, every={}ms)",
cfg.high_accuracy, cfg.background, cfg.max_accuracy_m, cfg.min_interval_ms
)),
_ => None,
}
}
pub fn get_path(&self) -> NodeTypeTag {
match self {
Self::Html => NodeTypeTag::Html,
Self::Head => NodeTypeTag::Head,
Self::Body => NodeTypeTag::Body,
Self::Div => NodeTypeTag::Div,
Self::P => NodeTypeTag::P,
Self::Article => NodeTypeTag::Article,
Self::Section => NodeTypeTag::Section,
Self::Nav => NodeTypeTag::Nav,
Self::Aside => NodeTypeTag::Aside,
Self::Header => NodeTypeTag::Header,
Self::Footer => NodeTypeTag::Footer,
Self::Main => NodeTypeTag::Main,
Self::Figure => NodeTypeTag::Figure,
Self::FigCaption => NodeTypeTag::FigCaption,
Self::H1 => NodeTypeTag::H1,
Self::H2 => NodeTypeTag::H2,
Self::H3 => NodeTypeTag::H3,
Self::H4 => NodeTypeTag::H4,
Self::H5 => NodeTypeTag::H5,
Self::H6 => NodeTypeTag::H6,
Self::Br => NodeTypeTag::Br,
Self::Hr => NodeTypeTag::Hr,
Self::Pre => NodeTypeTag::Pre,
Self::BlockQuote => NodeTypeTag::BlockQuote,
Self::Address => NodeTypeTag::Address,
Self::Details => NodeTypeTag::Details,
Self::Summary => NodeTypeTag::Summary,
Self::Dialog => NodeTypeTag::Dialog,
Self::Ul => NodeTypeTag::Ul,
Self::Ol => NodeTypeTag::Ol,
Self::Li => NodeTypeTag::Li,
Self::Dl => NodeTypeTag::Dl,
Self::Dt => NodeTypeTag::Dt,
Self::Dd => NodeTypeTag::Dd,
Self::Menu => NodeTypeTag::Menu,
Self::MenuItem => NodeTypeTag::MenuItem,
Self::Dir => NodeTypeTag::Dir,
Self::Table => NodeTypeTag::Table,
Self::Caption => NodeTypeTag::Caption,
Self::THead => NodeTypeTag::THead,
Self::TBody => NodeTypeTag::TBody,
Self::TFoot => NodeTypeTag::TFoot,
Self::Tr => NodeTypeTag::Tr,
Self::Th => NodeTypeTag::Th,
Self::Td => NodeTypeTag::Td,
Self::ColGroup => NodeTypeTag::ColGroup,
Self::Col => NodeTypeTag::Col,
Self::Form => NodeTypeTag::Form,
Self::FieldSet => NodeTypeTag::FieldSet,
Self::Legend => NodeTypeTag::Legend,
Self::Label => NodeTypeTag::Label,
Self::Input => NodeTypeTag::Input,
Self::Button => NodeTypeTag::Button,
Self::Select => NodeTypeTag::Select,
Self::OptGroup => NodeTypeTag::OptGroup,
Self::SelectOption => NodeTypeTag::SelectOption,
Self::TextArea => NodeTypeTag::TextArea,
Self::Output => NodeTypeTag::Output,
Self::Progress => NodeTypeTag::Progress,
Self::Meter => NodeTypeTag::Meter,
Self::DataList => NodeTypeTag::DataList,
Self::Span => NodeTypeTag::Span,
Self::A => NodeTypeTag::A,
Self::Em => NodeTypeTag::Em,
Self::Strong => NodeTypeTag::Strong,
Self::B => NodeTypeTag::B,
Self::I => NodeTypeTag::I,
Self::U => NodeTypeTag::U,
Self::S => NodeTypeTag::S,
Self::Mark => NodeTypeTag::Mark,
Self::Del => NodeTypeTag::Del,
Self::Ins => NodeTypeTag::Ins,
Self::Code => NodeTypeTag::Code,
Self::Samp => NodeTypeTag::Samp,
Self::Kbd => NodeTypeTag::Kbd,
Self::Var => NodeTypeTag::Var,
Self::Cite => NodeTypeTag::Cite,
Self::Dfn => NodeTypeTag::Dfn,
Self::Abbr => NodeTypeTag::Abbr,
Self::Acronym => NodeTypeTag::Acronym,
Self::Q => NodeTypeTag::Q,
Self::Time => NodeTypeTag::Time,
Self::Sub => NodeTypeTag::Sub,
Self::Sup => NodeTypeTag::Sup,
Self::Small => NodeTypeTag::Small,
Self::Big => NodeTypeTag::Big,
Self::Bdo => NodeTypeTag::Bdo,
Self::Bdi => NodeTypeTag::Bdi,
Self::Wbr => NodeTypeTag::Wbr,
Self::Ruby => NodeTypeTag::Ruby,
Self::Rt => NodeTypeTag::Rt,
Self::Rtc => NodeTypeTag::Rtc,
Self::Rp => NodeTypeTag::Rp,
Self::Data => NodeTypeTag::Data,
Self::Canvas => NodeTypeTag::Canvas,
Self::Object => NodeTypeTag::Object,
Self::Param => NodeTypeTag::Param,
Self::Embed => NodeTypeTag::Embed,
Self::Audio => NodeTypeTag::Audio,
Self::Video => NodeTypeTag::Video,
Self::Source => NodeTypeTag::Source,
Self::Track => NodeTypeTag::Track,
Self::Map => NodeTypeTag::Map,
Self::Area => NodeTypeTag::Area,
Self::Svg => NodeTypeTag::Svg,
Self::SvgG => NodeTypeTag::SvgG,
Self::SvgDefs => NodeTypeTag::SvgDefs,
Self::SvgSymbol => NodeTypeTag::SvgSymbol,
Self::SvgUse => NodeTypeTag::SvgUse,
Self::SvgSwitch => NodeTypeTag::SvgSwitch,
Self::SvgPath => NodeTypeTag::SvgPath,
Self::SvgCircle => NodeTypeTag::SvgCircle,
Self::SvgRect => NodeTypeTag::SvgRect,
Self::SvgEllipse => NodeTypeTag::SvgEllipse,
Self::SvgLine => NodeTypeTag::SvgLine,
Self::SvgPolygon => NodeTypeTag::SvgPolygon,
Self::SvgPolyline => NodeTypeTag::SvgPolyline,
Self::SvgText(_) => NodeTypeTag::SvgText,
Self::SvgTspan => NodeTypeTag::SvgTspan,
Self::SvgTextPath => NodeTypeTag::SvgTextPath,
Self::SvgLinearGradient => NodeTypeTag::SvgLinearGradient,
Self::SvgRadialGradient => NodeTypeTag::SvgRadialGradient,
Self::SvgStop => NodeTypeTag::SvgStop,
Self::SvgPattern => NodeTypeTag::SvgPattern,
Self::SvgClipPathElement => NodeTypeTag::SvgClipPathElement,
Self::SvgMask => NodeTypeTag::SvgMask,
Self::SvgFilter => NodeTypeTag::SvgFilter,
Self::SvgFeBlend => NodeTypeTag::SvgFeBlend,
Self::SvgFeColorMatrix => NodeTypeTag::SvgFeColorMatrix,
Self::SvgFeComponentTransfer => NodeTypeTag::SvgFeComponentTransfer,
Self::SvgFeComposite => NodeTypeTag::SvgFeComposite,
Self::SvgFeConvolveMatrix => NodeTypeTag::SvgFeConvolveMatrix,
Self::SvgFeDiffuseLighting => NodeTypeTag::SvgFeDiffuseLighting,
Self::SvgFeDisplacementMap => NodeTypeTag::SvgFeDisplacementMap,
Self::SvgFeDistantLight => NodeTypeTag::SvgFeDistantLight,
Self::SvgFeDropShadow => NodeTypeTag::SvgFeDropShadow,
Self::SvgFeFlood => NodeTypeTag::SvgFeFlood,
Self::SvgFeFuncR => NodeTypeTag::SvgFeFuncR,
Self::SvgFeFuncG => NodeTypeTag::SvgFeFuncG,
Self::SvgFeFuncB => NodeTypeTag::SvgFeFuncB,
Self::SvgFeFuncA => NodeTypeTag::SvgFeFuncA,
Self::SvgFeGaussianBlur => NodeTypeTag::SvgFeGaussianBlur,
Self::SvgFeImage => NodeTypeTag::SvgFeImage,
Self::SvgFeMerge => NodeTypeTag::SvgFeMerge,
Self::SvgFeMergeNode => NodeTypeTag::SvgFeMergeNode,
Self::SvgFeMorphology => NodeTypeTag::SvgFeMorphology,
Self::SvgFeOffset => NodeTypeTag::SvgFeOffset,
Self::SvgFePointLight => NodeTypeTag::SvgFePointLight,
Self::SvgFeSpecularLighting => NodeTypeTag::SvgFeSpecularLighting,
Self::SvgFeSpotLight => NodeTypeTag::SvgFeSpotLight,
Self::SvgFeTile => NodeTypeTag::SvgFeTile,
Self::SvgFeTurbulence => NodeTypeTag::SvgFeTurbulence,
Self::SvgMarker => NodeTypeTag::SvgMarker,
Self::SvgImage(_) => NodeTypeTag::SvgImage,
Self::SvgForeignObject => NodeTypeTag::SvgForeignObject,
Self::SvgTitle => NodeTypeTag::SvgTitle,
Self::SvgDesc => NodeTypeTag::SvgDesc,
Self::SvgMetadata => NodeTypeTag::SvgMetadata,
Self::SvgA => NodeTypeTag::SvgA,
Self::SvgView => NodeTypeTag::SvgView,
Self::SvgStyle => NodeTypeTag::SvgStyle,
Self::SvgScript => NodeTypeTag::SvgScript,
Self::SvgAnimate => NodeTypeTag::SvgAnimate,
Self::SvgAnimateMotion => NodeTypeTag::SvgAnimateMotion,
Self::SvgAnimateTransform => NodeTypeTag::SvgAnimateTransform,
Self::SvgSet => NodeTypeTag::SvgSet,
Self::SvgMpath => NodeTypeTag::SvgMpath,
Self::Title => NodeTypeTag::Title,
Self::Meta => NodeTypeTag::Meta,
Self::Link => NodeTypeTag::Link,
Self::Script => NodeTypeTag::Script,
Self::Style => NodeTypeTag::Style,
Self::Base => NodeTypeTag::Base,
Self::Text(_) => NodeTypeTag::Text,
Self::Image(_) => NodeTypeTag::Img,
Self::VirtualView => NodeTypeTag::VirtualView,
Self::Icon(_) => NodeTypeTag::Icon,
Self::GeolocationProbe(_) => NodeTypeTag::GeolocationProbe,
Self::Before => NodeTypeTag::Before,
Self::After => NodeTypeTag::After,
Self::Marker => NodeTypeTag::Marker,
Self::Placeholder => NodeTypeTag::Placeholder,
}
}
pub const fn is_semantic_for_accessibility(&self) -> bool {
matches!(
self,
Self::Button
| Self::Input
| Self::TextArea
| Self::Select
| Self::A
| Self::H1
| Self::H2
| Self::H3
| Self::H4
| Self::H5
| Self::H6
| Self::Article
| Self::Section
| Self::Nav
| Self::Main
| Self::Header
| Self::Footer
| Self::Aside
)
}
}
#[derive(Clone, PartialEq)]
pub enum FormattingContext {
Block {
establishes_new_context: bool,
},
Inline,
InlineBlock,
Flex,
Float(LayoutFloat),
OutOfFlow(LayoutPosition),
Table,
TableRowGroup,
TableRow,
TableCell,
TableColumnGroup,
TableCaption,
Grid,
Contents,
None,
}
impl fmt::Debug for FormattingContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FormattingContext::Block {
establishes_new_context,
} => write!(
f,
"Block {{ establishes_new_context: {establishes_new_context:?} }}"
),
FormattingContext::Inline => write!(f, "Inline"),
FormattingContext::InlineBlock => write!(f, "InlineBlock"),
FormattingContext::Flex => write!(f, "Flex"),
FormattingContext::Float(layout_float) => write!(f, "Float({layout_float:?})"),
FormattingContext::OutOfFlow(layout_position) => {
write!(f, "OutOfFlow({layout_position:?})")
}
FormattingContext::Grid => write!(f, "Grid"),
FormattingContext::None => write!(f, "None"),
FormattingContext::Table => write!(f, "Table"),
FormattingContext::TableRowGroup => write!(f, "TableRowGroup"),
FormattingContext::TableRow => write!(f, "TableRow"),
FormattingContext::TableCell => write!(f, "TableCell"),
FormattingContext::TableColumnGroup => write!(f, "TableColumnGroup"),
FormattingContext::TableCaption => write!(f, "TableCaption"),
FormattingContext::Contents => write!(f, "Contents"),
}
}
}
impl Default for FormattingContext {
fn default() -> Self {
FormattingContext::Block {
establishes_new_context: false,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(C)]
pub enum On {
MouseOver,
MouseDown,
LeftMouseDown,
MiddleMouseDown,
RightMouseDown,
MouseUp,
LeftMouseUp,
MiddleMouseUp,
RightMouseUp,
MouseEnter,
MouseLeave,
Scroll,
TextInput,
VirtualKeyDown,
VirtualKeyUp,
HoveredFile,
DroppedFile,
HoveredFileCancelled,
FocusReceived,
FocusLost,
Default,
Collapse,
Expand,
Increment,
Decrement,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct VirtualViewNode {
pub callback: VirtualViewCallback,
pub refany: RefAny,
}
#[repr(C, u8)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum IdOrClass {
Id(AzString),
Class(AzString),
}
impl_option!(
IdOrClass,
OptionIdOrClass,
copy = false,
[Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord]
);
impl_vec!(IdOrClass, IdOrClassVec, IdOrClassVecDestructor, IdOrClassVecDestructorType, IdOrClassVecSlice, OptionIdOrClass);
impl_vec_debug!(IdOrClass, IdOrClassVec);
impl_vec_partialord!(IdOrClass, IdOrClassVec);
impl_vec_ord!(IdOrClass, IdOrClassVec);
impl_vec_clone!(IdOrClass, IdOrClassVec, IdOrClassVecDestructor);
impl_vec_partialeq!(IdOrClass, IdOrClassVec);
impl_vec_eq!(IdOrClass, IdOrClassVec);
impl_vec_hash!(IdOrClass, IdOrClassVec);
impl IdOrClass {
pub fn as_id(&self) -> Option<&str> {
match self {
IdOrClass::Id(s) => Some(s.as_str()),
IdOrClass::Class(_) => None,
}
}
pub fn as_class(&self) -> Option<&str> {
match self {
IdOrClass::Class(s) => Some(s.as_str()),
IdOrClass::Id(_) => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct AttributeNameValue {
pub attr_name: AzString,
pub value: AzString,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C, u8)]
pub enum AttributeType {
Id(AzString),
Class(AzString),
AriaLabel(AzString),
AriaLabelledBy(AzString),
AriaDescribedBy(AzString),
AriaRole(AzString),
AriaState(AttributeNameValue),
AriaProperty(AttributeNameValue),
Href(AzString),
Rel(AzString),
Target(AzString),
Src(AzString),
Alt(AzString),
Title(AzString),
Name(AzString),
Value(AzString),
InputType(AzString),
Placeholder(AzString),
Required,
Disabled,
Readonly,
CheckedTrue,
CheckedFalse,
Selected,
Max(AzString),
Min(AzString),
Step(AzString),
Pattern(AzString),
MinLength(i32),
MaxLength(i32),
Autocomplete(AzString),
Scope(AzString),
ColSpan(i32),
RowSpan(i32),
TabIndex(i32),
Focusable,
Lang(AzString),
Dir(AzString),
ContentEditable(bool),
Draggable(bool),
Hidden,
Data(AttributeNameValue),
Custom(AttributeNameValue),
}
impl_option!(
AttributeType,
OptionAttributeType,
copy = false,
[Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_vec!(AttributeType, AttributeTypeVec, AttributeTypeVecDestructor, AttributeTypeVecDestructorType, AttributeTypeVecSlice, OptionAttributeType);
impl_vec_debug!(AttributeType, AttributeTypeVec);
impl_vec_partialord!(AttributeType, AttributeTypeVec);
impl_vec_ord!(AttributeType, AttributeTypeVec);
impl_vec_clone!(AttributeType, AttributeTypeVec, AttributeTypeVecDestructor);
impl_vec_partialeq!(AttributeType, AttributeTypeVec);
impl_vec_eq!(AttributeType, AttributeTypeVec);
impl_vec_hash!(AttributeType, AttributeTypeVec);
impl AttributeType {
pub fn as_id(&self) -> Option<&str> {
match self {
AttributeType::Id(s) => Some(s.as_str()),
_ => None,
}
}
pub fn as_class(&self) -> Option<&str> {
match self {
AttributeType::Class(s) => Some(s.as_str()),
_ => None,
}
}
pub fn name(&self) -> &str {
match self {
AttributeType::Id(_) => "id",
AttributeType::Class(_) => "class",
AttributeType::AriaLabel(_) => "aria-label",
AttributeType::AriaLabelledBy(_) => "aria-labelledby",
AttributeType::AriaDescribedBy(_) => "aria-describedby",
AttributeType::AriaRole(_) => "role",
AttributeType::AriaState(nv) => nv.attr_name.as_str(),
AttributeType::AriaProperty(nv) => nv.attr_name.as_str(),
AttributeType::Href(_) => "href",
AttributeType::Rel(_) => "rel",
AttributeType::Target(_) => "target",
AttributeType::Src(_) => "src",
AttributeType::Alt(_) => "alt",
AttributeType::Title(_) => "title",
AttributeType::Name(_) => "name",
AttributeType::Value(_) => "value",
AttributeType::InputType(_) => "type",
AttributeType::Placeholder(_) => "placeholder",
AttributeType::Required => "required",
AttributeType::Disabled => "disabled",
AttributeType::Readonly => "readonly",
AttributeType::CheckedTrue => "checked",
AttributeType::CheckedFalse => "checked",
AttributeType::Selected => "selected",
AttributeType::Max(_) => "max",
AttributeType::Min(_) => "min",
AttributeType::Step(_) => "step",
AttributeType::Pattern(_) => "pattern",
AttributeType::MinLength(_) => "minlength",
AttributeType::MaxLength(_) => "maxlength",
AttributeType::Autocomplete(_) => "autocomplete",
AttributeType::Scope(_) => "scope",
AttributeType::ColSpan(_) => "colspan",
AttributeType::RowSpan(_) => "rowspan",
AttributeType::TabIndex(_) => "tabindex",
AttributeType::Focusable => "tabindex",
AttributeType::Lang(_) => "lang",
AttributeType::Dir(_) => "dir",
AttributeType::ContentEditable(_) => "contenteditable",
AttributeType::Draggable(_) => "draggable",
AttributeType::Hidden => "hidden",
AttributeType::Data(nv) => nv.attr_name.as_str(),
AttributeType::Custom(nv) => nv.attr_name.as_str(),
}
}
pub fn value(&self) -> AzString {
match self {
AttributeType::Id(v)
| AttributeType::Class(v)
| AttributeType::AriaLabel(v)
| AttributeType::AriaLabelledBy(v)
| AttributeType::AriaDescribedBy(v)
| AttributeType::AriaRole(v)
| AttributeType::Href(v)
| AttributeType::Rel(v)
| AttributeType::Target(v)
| AttributeType::Src(v)
| AttributeType::Alt(v)
| AttributeType::Title(v)
| AttributeType::Name(v)
| AttributeType::Value(v)
| AttributeType::InputType(v)
| AttributeType::Placeholder(v)
| AttributeType::Max(v)
| AttributeType::Min(v)
| AttributeType::Step(v)
| AttributeType::Pattern(v)
| AttributeType::Autocomplete(v)
| AttributeType::Scope(v)
| AttributeType::Lang(v)
| AttributeType::Dir(v) => v.clone(),
AttributeType::AriaState(nv)
| AttributeType::AriaProperty(nv)
| AttributeType::Data(nv)
| AttributeType::Custom(nv) => nv.value.clone(),
AttributeType::MinLength(n)
| AttributeType::MaxLength(n)
| AttributeType::ColSpan(n)
| AttributeType::RowSpan(n)
| AttributeType::TabIndex(n) => n.to_string().into(),
AttributeType::Focusable => "0".into(),
AttributeType::ContentEditable(b) | AttributeType::Draggable(b) => {
if *b {
"true".into()
} else {
"false".into()
}
}
AttributeType::Required
| AttributeType::Disabled
| AttributeType::Readonly
| AttributeType::CheckedTrue
| AttributeType::CheckedFalse
| AttributeType::Selected
| AttributeType::Hidden => "".into(), }
}
pub fn is_boolean(&self) -> bool {
matches!(
self,
AttributeType::Required
| AttributeType::Disabled
| AttributeType::Readonly
| AttributeType::CheckedTrue
| AttributeType::CheckedFalse
| AttributeType::Selected
| AttributeType::Hidden
)
}
}
#[repr(C)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct NodeData {
pub node_type: NodeType,
pub callbacks: CoreCallbackDataVec,
pub style: azul_css::css::Css,
pub flags: NodeFlags,
pub accessibility: Option<Box<AccessibilityInfo>>,
extra: Option<Box<NodeDataExt>>,
}
impl_option!(
NodeData,
OptionNodeData,
copy = false,
[Debug, PartialEq, Eq, PartialOrd, Ord]
);
impl Hash for NodeData {
fn hash<H: Hasher>(&self, state: &mut H) {
self.node_type.hash(state);
self.attributes().as_ref().hash(state);
self.flags.hash(state);
for callback in self.callbacks.as_ref().iter() {
callback.event.hash(state);
callback.callback.hash(state);
callback.refany.get_type_id().hash(state);
}
for (prop, _conds) in self.style.iter_inline_properties() {
core::mem::discriminant(prop).hash(state);
}
if let Some(ext) = self.extra.as_ref() {
if let Some(ds) = ext.dataset.as_ref() {
ds.hash(state);
}
if let Some(c) = ext.svg_data.as_ref() {
c.hash(state);
}
if let Some(c) = ext.menu_bar.as_ref() {
c.hash(state);
}
if let Some(c) = ext.context_menu.as_ref() {
c.hash(state);
}
if let Some(vv) = ext.virtual_view.as_ref() {
vv.hash(state);
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ComponentOrigin {
pub component_id: AzString,
pub data_model_json: crate::json::Json,
}
impl Eq for ComponentOrigin {}
impl PartialOrd for ComponentOrigin {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ComponentOrigin {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.component_id.cmp(&other.component_id)
.then_with(|| {
let a = alloc::format!("{}", self.data_model_json);
let b = alloc::format!("{}", other.data_model_json);
a.cmp(&b)
})
}
}
impl core::hash::Hash for ComponentOrigin {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.component_id.hash(state);
let s = alloc::format!("{}", self.data_model_json);
s.hash(state);
}
}
impl Default for ComponentOrigin {
fn default() -> Self {
Self {
component_id: AzString::from_const_str(""),
data_model_json: crate::json::Json::null(),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum SvgNodeData {
ImageClipMask(ImageMask),
Path(crate::svg::SvgMultiPolygon),
Circle { cx: f32, cy: f32, r: f32 },
Rect { x: f32, y: f32, width: f32, height: f32, rx: f32, ry: f32 },
Ellipse { cx: f32, cy: f32, rx: f32, ry: f32 },
Line { x1: f32, y1: f32, x2: f32, y2: f32 },
PointsList { points: alloc::vec::Vec<azul_css::props::basic::SvgPoint>, closed: bool },
ViewBox { min_x: f32, min_y: f32, width: f32, height: f32 },
LinearGradient { x1: f32, y1: f32, x2: f32, y2: f32 },
RadialGradient { cx: f32, cy: f32, r: f32, fx: f32, fy: f32 },
GradientStop { offset: f32 },
Use { href: AzString, x: f32, y: f32 },
SvgImageData { href: AzString, x: f32, y: f32, width: f32, height: f32 },
}
impl Eq for SvgNodeData {}
impl Ord for SvgNodeData {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.partial_cmp(other).unwrap_or(core::cmp::Ordering::Equal)
}
}
impl Hash for SvgNodeData {
fn hash<H: Hasher>(&self, state: &mut H) {
core::mem::discriminant(self).hash(state);
match self {
SvgNodeData::ImageClipMask(m) => m.hash(state),
SvgNodeData::Path(mp) => {
for ring in mp.rings.as_ref().iter() {
for item in ring.items.as_ref().iter() {
match item {
crate::svg::SvgPathElement::Line(l) => {
0u8.hash(state);
l.start.x.to_bits().hash(state);
l.start.y.to_bits().hash(state);
l.end.x.to_bits().hash(state);
l.end.y.to_bits().hash(state);
}
crate::svg::SvgPathElement::QuadraticCurve(q) => {
1u8.hash(state);
q.start.x.to_bits().hash(state);
q.start.y.to_bits().hash(state);
q.ctrl.x.to_bits().hash(state);
q.ctrl.y.to_bits().hash(state);
q.end.x.to_bits().hash(state);
q.end.y.to_bits().hash(state);
}
crate::svg::SvgPathElement::CubicCurve(c) => {
2u8.hash(state);
c.start.x.to_bits().hash(state);
c.start.y.to_bits().hash(state);
c.ctrl_1.x.to_bits().hash(state);
c.ctrl_1.y.to_bits().hash(state);
c.ctrl_2.x.to_bits().hash(state);
c.ctrl_2.y.to_bits().hash(state);
c.end.x.to_bits().hash(state);
c.end.y.to_bits().hash(state);
}
}
}
}
}
SvgNodeData::Circle { cx, cy, r } => {
cx.to_bits().hash(state); cy.to_bits().hash(state); r.to_bits().hash(state);
}
SvgNodeData::Rect { x, y, width, height, rx, ry } => {
x.to_bits().hash(state); y.to_bits().hash(state);
width.to_bits().hash(state); height.to_bits().hash(state);
rx.to_bits().hash(state); ry.to_bits().hash(state);
}
SvgNodeData::Ellipse { cx, cy, rx, ry } => {
cx.to_bits().hash(state); cy.to_bits().hash(state);
rx.to_bits().hash(state); ry.to_bits().hash(state);
}
SvgNodeData::Line { x1, y1, x2, y2 } => {
x1.to_bits().hash(state); y1.to_bits().hash(state);
x2.to_bits().hash(state); y2.to_bits().hash(state);
}
SvgNodeData::PointsList { points, closed } => {
for p in points.iter() {
p.x.to_bits().hash(state); p.y.to_bits().hash(state);
}
closed.hash(state);
}
SvgNodeData::ViewBox { min_x, min_y, width, height } => {
min_x.to_bits().hash(state); min_y.to_bits().hash(state);
width.to_bits().hash(state); height.to_bits().hash(state);
}
SvgNodeData::LinearGradient { x1, y1, x2, y2 } => {
x1.to_bits().hash(state); y1.to_bits().hash(state);
x2.to_bits().hash(state); y2.to_bits().hash(state);
}
SvgNodeData::RadialGradient { cx, cy, r, fx, fy } => {
cx.to_bits().hash(state); cy.to_bits().hash(state);
r.to_bits().hash(state); fx.to_bits().hash(state);
fy.to_bits().hash(state);
}
SvgNodeData::GradientStop { offset } => {
offset.to_bits().hash(state);
}
SvgNodeData::Use { href, x, y } => {
href.hash(state);
x.to_bits().hash(state); y.to_bits().hash(state);
}
SvgNodeData::SvgImageData { href, x, y, width, height } => {
href.hash(state);
x.to_bits().hash(state); y.to_bits().hash(state);
width.to_bits().hash(state); height.to_bits().hash(state);
}
}
}
}
#[repr(C)]
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct NodeDataExt {
pub attributes: AttributeTypeVec,
pub virtual_view: Option<VirtualViewNode>,
pub dataset: Option<RefAny>,
pub svg_data: Option<SvgNodeData>,
pub menu_bar: Option<Box<Menu>>,
pub context_menu: Option<Box<Menu>>,
pub key: Option<u64>,
pub dataset_merge_callback: Option<DatasetMergeCallback>,
pub component_origin: Option<ComponentOrigin>,
}
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(C)]
pub struct DatasetMergeCallback {
pub cb: DatasetMergeCallbackType,
pub callable: OptionRefAny,
}
impl core::fmt::Debug for DatasetMergeCallback {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DatasetMergeCallback")
.field("cb", &(self.cb as usize))
.field("callable", &self.callable)
.finish()
}
}
impl From<DatasetMergeCallbackType> for DatasetMergeCallback {
fn from(cb: DatasetMergeCallbackType) -> Self {
DatasetMergeCallback {
cb,
callable: OptionRefAny::None,
}
}
}
impl_option!(
DatasetMergeCallback,
OptionDatasetMergeCallback,
copy = false,
[Debug, Clone]
);
pub type DatasetMergeCallbackType = extern "C" fn(RefAny, RefAny) -> RefAny;
impl Clone for NodeData {
#[inline]
fn clone(&self) -> Self {
Self {
node_type: self.node_type.into_library_owned_nodetype(),
style: self.style.clone(),
callbacks: self.callbacks.clone(),
flags: self.flags,
accessibility: self.accessibility.clone(),
extra: self.extra.clone(),
}
}
}
impl_vec!(NodeData, NodeDataVec, NodeDataVecDestructor, NodeDataVecDestructorType, NodeDataVecSlice, OptionNodeData);
impl_vec_clone!(NodeData, NodeDataVec, NodeDataVecDestructor);
impl_vec_mut!(NodeData, NodeDataVec);
impl_vec_debug!(NodeData, NodeDataVec);
impl_vec_partialord!(NodeData, NodeDataVec);
impl_vec_ord!(NodeData, NodeDataVec);
impl_vec_partialeq!(NodeData, NodeDataVec);
impl_vec_eq!(NodeData, NodeDataVec);
impl_vec_hash!(NodeData, NodeDataVec);
impl NodeDataVec {
#[inline]
pub fn as_container<'a>(&'a self) -> NodeDataContainerRef<'a, NodeData> {
NodeDataContainerRef {
internal: self.as_ref(),
}
}
#[inline]
pub fn as_container_mut<'a>(&'a mut self) -> NodeDataContainerRefMut<'a, NodeData> {
NodeDataContainerRefMut {
internal: self.as_mut(),
}
}
}
unsafe impl Send for NodeData {}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C, u8)]
pub enum TabIndex {
Auto,
OverrideInParent(u32),
NoKeyboardFocus,
}
impl_option!(
TabIndex,
OptionTabIndex,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl TabIndex {
pub fn get_index(&self) -> isize {
use self::TabIndex::*;
match self {
Auto => 0,
OverrideInParent(x) => *x as isize,
NoKeyboardFocus => -1,
}
}
}
impl Default for TabIndex {
fn default() -> Self {
TabIndex::Auto
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NodeFlags {
pub inner: u32,
}
impl Default for NodeFlags {
fn default() -> Self {
NodeFlags { inner: 0 }
}
}
impl NodeFlags {
const CONTENTEDITABLE_BIT: u32 = 1 << 31;
const TAB_INDEX_MASK: u32 = 0b11 << 29;
const ANONYMOUS_BIT: u32 = 1 << 28;
const TAB_VALUE_MASK: u32 = (1 << 28) - 1;
const TAB_NONE: u32 = 0b00 << 29;
const TAB_AUTO: u32 = 0b01 << 29;
const TAB_OVERRIDE: u32 = 0b10 << 29;
const TAB_NO_KEYBOARD: u32 = 0b11 << 29;
pub const fn new() -> Self {
NodeFlags { inner: 0 }
}
pub const fn is_contenteditable(&self) -> bool {
(self.inner & Self::CONTENTEDITABLE_BIT) != 0
}
pub const fn set_contenteditable(mut self, v: bool) -> Self {
if v {
self.inner |= Self::CONTENTEDITABLE_BIT;
} else {
self.inner &= !Self::CONTENTEDITABLE_BIT;
}
self
}
pub fn set_contenteditable_mut(&mut self, v: bool) {
if v {
self.inner |= Self::CONTENTEDITABLE_BIT;
} else {
self.inner &= !Self::CONTENTEDITABLE_BIT;
}
}
pub fn get_tab_index(&self) -> Option<TabIndex> {
match self.inner & Self::TAB_INDEX_MASK {
x if x == Self::TAB_NONE => None,
x if x == Self::TAB_AUTO => Some(TabIndex::Auto),
x if x == Self::TAB_OVERRIDE => {
let val = self.inner & Self::TAB_VALUE_MASK;
Some(TabIndex::OverrideInParent(val))
}
x if x == Self::TAB_NO_KEYBOARD => Some(TabIndex::NoKeyboardFocus),
_ => None,
}
}
pub const fn is_anonymous(&self) -> bool {
(self.inner & Self::ANONYMOUS_BIT) != 0
}
pub fn set_anonymous(&mut self, v: bool) {
if v {
self.inner |= Self::ANONYMOUS_BIT;
} else {
self.inner &= !Self::ANONYMOUS_BIT;
}
}
pub fn set_tab_index(&mut self, tab_index: Option<TabIndex>) {
self.inner &= Self::CONTENTEDITABLE_BIT | Self::ANONYMOUS_BIT;
match tab_index {
None => { }
Some(TabIndex::Auto) => {
self.inner |= Self::TAB_AUTO;
}
Some(TabIndex::OverrideInParent(val)) => {
self.inner |= Self::TAB_OVERRIDE | (val & Self::TAB_VALUE_MASK);
}
Some(TabIndex::NoKeyboardFocus) => {
self.inner |= Self::TAB_NO_KEYBOARD;
}
}
}
}
impl Default for NodeData {
fn default() -> Self {
NodeData::create_node(NodeType::Div)
}
}
impl fmt::Display for NodeData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let html_type = self.node_type.get_path();
let attributes_string = node_data_to_string(&self);
match self.node_type.format() {
Some(content) => write!(
f,
"<{}{}>{}</{}>",
html_type, attributes_string, content, html_type
),
None => write!(f, "<{}{}/>", html_type, attributes_string),
}
}
}
fn node_data_to_string(node_data: &NodeData) -> String {
let mut id_string = String::new();
let ids = node_data
.attributes()
.as_ref()
.iter()
.filter_map(|s| s.as_id())
.collect::<Vec<_>>()
.join(" ");
if !ids.is_empty() {
id_string = format!(" id=\"{}\" ", ids);
}
let mut class_string = String::new();
let classes = node_data
.attributes()
.as_ref()
.iter()
.filter_map(|s| s.as_class())
.collect::<Vec<_>>()
.join(" ");
if !classes.is_empty() {
class_string = format!(" class=\"{}\" ", classes);
}
let mut tabindex_string = String::new();
if let Some(tab_index) = node_data.get_tab_index() {
tabindex_string = format!(" tabindex=\"{}\" ", tab_index.get_index());
};
format!("{}{}{}", id_string, class_string, tabindex_string)
}
impl NodeData {
#[inline]
pub const fn create_node(node_type: NodeType) -> Self {
Self {
node_type,
callbacks: CoreCallbackDataVec::from_const_slice(&[]),
style: azul_css::css::Css {
rules: azul_css::css::CssRuleBlockVec::from_const_slice(&[]),
},
flags: NodeFlags::new(),
accessibility: None,
extra: None,
}
}
#[inline]
pub fn attributes(&self) -> &AttributeTypeVec {
static EMPTY: AttributeTypeVec = AttributeTypeVec::from_const_slice(&[]);
match &self.extra {
Some(ext) => &ext.attributes,
None => &EMPTY,
}
}
#[inline]
pub fn attributes_mut(&mut self) -> &mut AttributeTypeVec {
&mut self.extra.get_or_insert_with(|| Box::new(NodeDataExt::default())).attributes
}
#[inline]
pub fn set_attributes(&mut self, attrs: AttributeTypeVec) {
self.extra.get_or_insert_with(|| Box::new(NodeDataExt::default())).attributes = attrs;
}
#[inline(always)]
pub const fn create_body() -> Self {
Self::create_node(NodeType::Body)
}
#[inline(always)]
pub const fn create_div() -> Self {
Self::create_node(NodeType::Div)
}
#[inline(always)]
pub const fn create_br() -> Self {
Self::create_node(NodeType::Br)
}
#[inline(always)]
pub fn create_text<S: Into<AzString>>(value: S) -> Self {
Self::create_node(NodeType::Text(BoxOrStatic::heap(value.into())))
}
#[inline(always)]
pub fn create_image(image: ImageRef) -> Self {
Self::create_node(NodeType::Image(BoxOrStatic::heap(image)))
}
#[inline(always)]
pub fn create_virtual_view(data: RefAny, callback: impl Into<VirtualViewCallback>) -> Self {
let mut nd = Self::create_node(NodeType::VirtualView);
let ext = nd.extra.get_or_insert_with(|| Box::new(NodeDataExt::default()));
ext.virtual_view = Some(VirtualViewNode {
callback: callback.into(),
refany: data,
});
nd
}
fn with_attribute(mut self, attr: AttributeType) -> Self {
let mut v = self.attributes().clone().into_library_owned_vec();
v.push(attr);
self.set_attributes(v.into());
self
}
#[inline]
pub fn create_button(aria: SmallAriaInfo) -> Self {
let mut nd = Self::create_node(NodeType::Button);
nd.set_accessibility_info(aria.to_full_info());
nd
}
#[inline]
pub fn create_button_no_a11y() -> Self {
Self::create_node(NodeType::Button)
}
#[inline]
pub fn create_a(href: AzString, aria: SmallAriaInfo) -> Self {
let mut nd = Self::create_node(NodeType::A).with_attribute(AttributeType::Href(href));
nd.set_accessibility_info(aria.to_full_info());
nd
}
#[inline]
pub fn create_a_no_a11y(href: AzString) -> Self {
Self::create_node(NodeType::A).with_attribute(AttributeType::Href(href))
}
#[inline]
pub fn create_input(
input_type: AzString,
name: AzString,
label: AzString,
aria: SmallAriaInfo,
) -> Self {
let mut nd = Self::create_node(NodeType::Input)
.with_attribute(AttributeType::InputType(input_type))
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label));
nd.set_accessibility_info(aria.to_full_info());
nd
}
#[inline]
pub fn create_input_no_a11y(input_type: AzString, name: AzString, label: AzString) -> Self {
Self::create_node(NodeType::Input)
.with_attribute(AttributeType::InputType(input_type))
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label))
}
#[inline]
pub fn create_textarea(name: AzString, label: AzString, aria: SmallAriaInfo) -> Self {
let mut nd = Self::create_node(NodeType::TextArea)
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label));
nd.set_accessibility_info(aria.to_full_info());
nd
}
#[inline]
pub fn create_textarea_no_a11y(name: AzString, label: AzString) -> Self {
Self::create_node(NodeType::TextArea)
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label))
}
#[inline]
pub fn create_select(name: AzString, label: AzString, aria: SmallAriaInfo) -> Self {
let mut nd = Self::create_node(NodeType::Select)
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label));
nd.set_accessibility_info(aria.to_full_info());
nd
}
#[inline]
pub fn create_select_no_a11y(name: AzString, label: AzString) -> Self {
Self::create_node(NodeType::Select)
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label))
}
#[inline]
pub fn create_table(aria: SmallAriaInfo) -> Self {
let mut nd = Self::create_node(NodeType::Table);
nd.set_accessibility_info(aria.to_full_info());
nd
}
#[inline]
pub fn create_table_no_a11y() -> Self {
Self::create_node(NodeType::Table)
}
#[inline]
pub fn create_label(for_id: AzString, aria: SmallAriaInfo) -> Self {
let mut nd = Self::create_node(NodeType::Label).with_attribute(AttributeType::Custom(
AttributeNameValue {
attr_name: "for".into(),
value: for_id,
},
));
nd.set_accessibility_info(aria.to_full_info());
nd
}
#[inline]
pub fn create_label_no_a11y(for_id: AzString) -> Self {
Self::create_node(NodeType::Label).with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "for".into(),
value: for_id,
}))
}
#[inline]
pub fn is_node_type(&self, searched_type: NodeType) -> bool {
self.node_type == searched_type
}
pub fn has_id(&self, id: &str) -> bool {
self.attributes()
.iter()
.any(|attr| attr.as_id() == Some(id))
}
pub fn has_class(&self, class: &str) -> bool {
self.attributes()
.iter()
.any(|attr| attr.as_class() == Some(class))
}
pub fn has_context_menu(&self) -> bool {
self.extra
.as_ref()
.map(|m| m.context_menu.is_some())
.unwrap_or(false)
}
pub fn is_text_node(&self) -> bool {
matches!(self.node_type, NodeType::Text(_))
}
pub fn is_virtual_view_node(&self) -> bool {
matches!(self.node_type, NodeType::VirtualView)
}
#[inline(always)]
pub const fn get_node_type(&self) -> &NodeType {
&self.node_type
}
#[inline]
pub fn get_dataset_mut(&mut self) -> Option<&mut RefAny> {
self.extra.as_mut().and_then(|e| e.dataset.as_mut())
}
#[inline]
pub fn get_dataset(&self) -> Option<&RefAny> {
self.extra.as_ref().and_then(|e| e.dataset.as_ref())
}
pub fn take_dataset(&mut self) -> Option<RefAny> {
self.extra.as_mut().and_then(|e| e.dataset.take())
}
#[inline]
pub fn get_ids_and_classes(&self) -> IdOrClassVec {
let v: Vec<IdOrClass> = self.attributes().as_ref().iter().filter_map(|attr| {
match attr {
AttributeType::Id(s) => Some(IdOrClass::Id(s.clone())),
AttributeType::Class(s) => Some(IdOrClass::Class(s.clone())),
_ => None,
}
}).collect();
v.into()
}
#[inline(always)]
pub const fn get_callbacks(&self) -> &CoreCallbackDataVec {
&self.callbacks
}
#[inline(always)]
pub const fn get_style(&self) -> &azul_css::css::Css {
&self.style
}
#[inline]
pub fn get_svg_data(&self) -> Option<&SvgNodeData> {
self.extra.as_ref().and_then(|e| e.svg_data.as_ref())
}
#[inline]
pub fn get_image_clip_mask(&self) -> Option<&ImageMask> {
match self.get_svg_data()? {
SvgNodeData::ImageClipMask(m) => Some(m),
_ => None,
}
}
#[inline]
pub fn get_tab_index(&self) -> Option<TabIndex> {
self.flags.get_tab_index()
}
#[inline]
pub fn get_accessibility_info(&self) -> Option<&Box<AccessibilityInfo>> {
self.accessibility.as_ref()
}
#[inline]
pub fn get_menu_bar(&self) -> Option<&Box<Menu>> {
self.extra.as_ref().and_then(|e| e.menu_bar.as_ref())
}
#[inline]
pub fn get_context_menu(&self) -> Option<&Box<Menu>> {
self.extra.as_ref().and_then(|e| e.context_menu.as_ref())
}
#[inline]
pub fn is_anonymous(&self) -> bool {
self.flags.is_anonymous()
}
#[inline(always)]
pub fn set_node_type(&mut self, node_type: NodeType) {
self.node_type = node_type;
}
#[inline]
pub fn set_dataset(&mut self, data: OptionRefAny) {
match data {
OptionRefAny::None => {
if let Some(ext) = self.extra.as_mut() {
ext.dataset = None;
}
}
OptionRefAny::Some(r) => {
self.extra
.get_or_insert_with(|| Box::new(NodeDataExt::default()))
.dataset = Some(r);
}
}
}
#[inline]
pub fn set_ids_and_classes(&mut self, ids_and_classes: IdOrClassVec) {
let mut v: AttributeTypeVec = Vec::new().into();
mem::swap(&mut v, self.attributes_mut());
let mut v = v.into_library_owned_vec();
v.retain(|a| !matches!(a, AttributeType::Id(_) | AttributeType::Class(_)));
for ioc in ids_and_classes.as_ref().iter() {
match ioc {
IdOrClass::Id(s) => v.push(AttributeType::Id(s.clone())),
IdOrClass::Class(s) => v.push(AttributeType::Class(s.clone())),
}
}
self.set_attributes(v.into());
}
#[inline(always)]
pub fn set_callbacks(&mut self, callbacks: CoreCallbackDataVec) {
self.callbacks = callbacks;
}
#[inline(always)]
pub fn set_css_props(&mut self, css_props: CssPropertyWithConditionsVec) {
self.style = css_props.into();
}
#[inline(always)]
pub fn set_style(&mut self, style: azul_css::css::Css) {
self.style = style;
}
#[inline]
pub fn set_clip_mask(&mut self, clip_mask: ImageMask) {
self.extra
.get_or_insert_with(|| Box::new(NodeDataExt::default()))
.svg_data = Some(SvgNodeData::ImageClipMask(clip_mask));
}
#[inline]
pub fn set_svg_data(&mut self, data: SvgNodeData) {
self.extra
.get_or_insert_with(|| Box::new(NodeDataExt::default()))
.svg_data = Some(data);
}
#[inline]
pub fn set_tab_index(&mut self, tab_index: TabIndex) {
self.flags.set_tab_index(Some(tab_index));
}
#[inline]
pub fn set_contenteditable(&mut self, contenteditable: bool) {
self.flags.set_contenteditable_mut(contenteditable);
}
#[inline]
pub fn is_contenteditable(&self) -> bool {
self.flags.is_contenteditable()
}
#[inline]
pub fn set_accessibility_info(&mut self, accessibility_info: AccessibilityInfo) {
self.accessibility = Some(Box::new(accessibility_info));
}
#[inline]
pub fn set_anonymous(&mut self, is_anonymous: bool) {
self.flags.set_anonymous(is_anonymous);
}
#[inline]
pub fn set_menu_bar(&mut self, menu_bar: Menu) {
self.extra
.get_or_insert_with(|| Box::new(NodeDataExt::default()))
.menu_bar = Some(Box::new(menu_bar));
}
#[inline]
pub fn set_context_menu(&mut self, context_menu: Menu) {
self.extra
.get_or_insert_with(|| Box::new(NodeDataExt::default()))
.context_menu = Some(Box::new(context_menu));
}
#[inline]
pub fn set_key<K: core::hash::Hash>(&mut self, key: K) {
use std::hash::Hasher;
let mut hasher = std::hash::DefaultHasher::new();
key.hash(&mut hasher);
self.extra
.get_or_insert_with(|| Box::new(NodeDataExt::default()))
.key = Some(hasher.finish());
}
#[inline]
pub fn get_key(&self) -> Option<u64> {
self.extra.as_ref().and_then(|ext| ext.key)
}
#[inline]
pub fn set_merge_callback<C: Into<DatasetMergeCallback>>(&mut self, callback: C) {
self.extra
.get_or_insert_with(|| Box::new(NodeDataExt::default()))
.dataset_merge_callback = Some(callback.into());
}
#[inline]
pub fn get_merge_callback(&self) -> Option<DatasetMergeCallback> {
self.extra.as_ref().and_then(|ext| ext.dataset_merge_callback.clone())
}
#[inline]
pub fn set_component_origin(&mut self, origin: ComponentOrigin) {
self.extra
.get_or_insert_with(|| Box::new(NodeDataExt::default()))
.component_origin = Some(origin);
}
#[inline]
pub fn get_component_origin(&self) -> Option<&ComponentOrigin> {
self.extra.as_ref().and_then(|ext| ext.component_origin.as_ref())
}
#[inline]
pub fn with_menu_bar(mut self, menu_bar: Menu) -> Self {
self.set_menu_bar(menu_bar);
self
}
#[inline]
pub fn with_context_menu(mut self, context_menu: Menu) -> Self {
self.set_context_menu(context_menu);
self
}
#[inline]
pub fn add_callback<C: Into<CoreCallback>>(
&mut self,
event: EventFilter,
data: RefAny,
callback: C,
) {
let callback = callback.into();
let mut v: CoreCallbackDataVec = Vec::new().into();
mem::swap(&mut v, &mut self.callbacks);
let mut v = v.into_library_owned_vec();
v.push(CoreCallbackData {
event,
refany: data,
callback,
});
self.callbacks = v.into();
}
#[inline]
pub fn add_id(&mut self, s: AzString) {
let mut v: AttributeTypeVec = Vec::new().into();
mem::swap(&mut v, self.attributes_mut());
let mut v = v.into_library_owned_vec();
v.push(AttributeType::Id(s));
self.set_attributes(v.into());
}
#[inline]
pub fn add_class(&mut self, s: AzString) {
let mut v: AttributeTypeVec = Vec::new().into();
mem::swap(&mut v, self.attributes_mut());
let mut v = v.into_library_owned_vec();
v.push(AttributeType::Class(s));
self.set_attributes(v.into());
}
#[inline]
pub fn add_css_property(&mut self, p: CssPropertyWithConditions) {
use azul_css::css::{rule_priority, CssDeclaration, CssPath, CssRuleBlock};
let rule = CssRuleBlock {
path: CssPath { selectors: Vec::new().into() },
declarations: vec![CssDeclaration::Static(p.property)].into(),
conditions: p.apply_if,
priority: rule_priority::INLINE,
};
let mut v: azul_css::css::CssRuleBlockVec = Vec::new().into();
mem::swap(&mut v, &mut self.style.rules);
let mut v = v.into_library_owned_vec();
v.push(rule);
self.style.rules = v.into();
}
pub fn calculate_node_data_hash(&self) -> DomNodeHash {
use std::hash::Hasher;
let mut hasher = std::hash::DefaultHasher::new();
self.hash(&mut hasher);
let h = hasher.finish();
DomNodeHash { inner: h }
}
pub fn calculate_structural_hash(&self) -> DomNodeHash {
use std::hash::Hasher;
use core::hash::Hasher as StdHasher;
let mut hasher = std::hash::DefaultHasher::new();
core::mem::discriminant(&self.node_type).hash(&mut hasher);
if let NodeType::VirtualView = self.node_type {
if let Some(ext) = self.extra.as_ref() {
if let Some(vv) = ext.virtual_view.as_ref() {
vv.hash(&mut hasher);
}
}
}
if let NodeType::Image(ref img_ref) = self.node_type {
match img_ref.get_data() {
crate::resources::DecodedImage::Callback(cb) => {
cb.callback.cb.hash(&mut hasher);
cb.refany.get_type_id().hash(&mut hasher);
}
_ => {
img_ref.hash(&mut hasher);
}
}
}
for attr in self.attributes().as_ref().iter() {
match attr {
AttributeType::Id(s) => { 0u8.hash(&mut hasher); s.as_str().hash(&mut hasher); }
AttributeType::Class(s) => { 1u8.hash(&mut hasher); s.as_str().hash(&mut hasher); }
_ => {}
}
}
for attr in self.attributes().as_ref().iter() {
if !matches!(attr, AttributeType::ContentEditable(_) | AttributeType::Id(_) | AttributeType::Class(_)) {
attr.hash(&mut hasher);
}
}
for callback in self.callbacks.as_ref().iter() {
callback.event.hash(&mut hasher);
}
let h = hasher.finish();
DomNodeHash { inner: h }
}
#[inline(always)]
pub fn with_tab_index(mut self, tab_index: TabIndex) -> Self {
self.set_tab_index(tab_index);
self
}
#[inline(always)]
pub fn with_contenteditable(mut self, contenteditable: bool) -> Self {
self.set_contenteditable(contenteditable);
self
}
#[inline(always)]
pub fn with_node_type(mut self, node_type: NodeType) -> Self {
self.set_node_type(node_type);
self
}
#[inline(always)]
pub fn with_callback<C: Into<CoreCallback>>(
mut self,
event: EventFilter,
data: RefAny,
callback: C,
) -> Self {
self.add_callback(event, data, callback);
self
}
#[inline(always)]
pub fn with_dataset(mut self, data: OptionRefAny) -> Self {
self.set_dataset(data);
self
}
#[inline(always)]
pub fn with_ids_and_classes(mut self, ids_and_classes: IdOrClassVec) -> Self {
self.set_ids_and_classes(ids_and_classes);
self
}
#[inline(always)]
pub fn with_callbacks(mut self, callbacks: CoreCallbackDataVec) -> Self {
self.callbacks = callbacks;
self
}
#[inline(always)]
pub fn with_css_props(mut self, css_props: CssPropertyWithConditionsVec) -> Self {
self.style = css_props.into();
self
}
#[inline(always)]
pub fn with_style(mut self, style: azul_css::css::Css) -> Self {
self.style = style;
self
}
#[inline]
pub fn with_key<K: core::hash::Hash>(mut self, key: K) -> Self {
self.set_key(key);
self
}
#[inline]
pub fn with_merge_callback<C: Into<DatasetMergeCallback>>(mut self, callback: C) -> Self {
self.set_merge_callback(callback);
self
}
pub fn set_css(&mut self, style: &str) {
let parsed = azul_css::css::Css::parse_inline(style);
let mut current: azul_css::css::CssRuleBlockVec = Vec::new().into();
mem::swap(&mut current, &mut self.style.rules);
let mut v = current.into_library_owned_vec();
v.extend(parsed.rules.into_library_owned_vec());
self.style.rules = v.into();
}
pub fn with_css(mut self, style: &str) -> Self {
self.set_css(style);
self
}
#[inline(always)]
pub fn swap_with_default(&mut self) -> Self {
let mut s = NodeData::create_div();
mem::swap(&mut s, self);
s
}
#[inline]
pub fn copy_special(&self) -> Self {
Self {
node_type: self.node_type.into_library_owned_nodetype(),
style: self.style.clone(),
callbacks: self.callbacks.clone(),
flags: self.flags,
accessibility: self.accessibility.clone(),
extra: self.extra.clone(),
}
}
pub fn is_focusable(&self) -> bool {
if matches!(self.node_type,
NodeType::A | NodeType::Button | NodeType::Input
| NodeType::Select | NodeType::TextArea
) {
return true;
}
if self.is_contenteditable() {
return true;
}
self.get_tab_index().is_some()
|| self
.get_callbacks()
.iter()
.any(|cb| cb.event.is_focus_callback())
}
pub fn has_activation_behavior(&self) -> bool {
if matches!(self.node_type, NodeType::A | NodeType::Button) {
return true;
}
use crate::events::{EventFilter, HoverEventFilter};
let has_click_callback = self
.get_callbacks()
.iter()
.any(|cb| matches!(
cb.event,
EventFilter::Hover(HoverEventFilter::MouseUp)
| EventFilter::Hover(HoverEventFilter::LeftMouseUp)
));
if has_click_callback {
return true;
}
if let Some(ref accessibility) = self.accessibility {
use crate::a11y::AccessibilityRole;
match accessibility.role {
AccessibilityRole::PushButton | AccessibilityRole::Link
| AccessibilityRole::CheckButton | AccessibilityRole::RadioButton | AccessibilityRole::MenuItem
| AccessibilityRole::PageTab => return true,
_ => {}
}
}
false
}
pub fn is_activatable(&self) -> bool {
if !self.has_activation_behavior() {
return false;
}
if let Some(ref accessibility) = self.accessibility {
if accessibility
.states
.as_ref()
.iter()
.any(|s| matches!(s, AccessibilityState::Unavailable))
{
return false;
}
}
true
}
pub fn get_effective_tabindex(&self) -> Option<i32> {
match self.flags.get_tab_index() {
None => {
if self.get_callbacks().iter().any(|cb| cb.event.is_focus_callback()) {
Some(0)
} else {
None
}
}
Some(tab_idx) => {
match tab_idx {
TabIndex::Auto => Some(0),
TabIndex::OverrideInParent(n) => Some(n as i32),
TabIndex::NoKeyboardFocus => Some(-1),
}
}
}
}
pub fn get_accessible_label(&self) -> Option<&str> {
for attr in self.attributes().as_ref() {
match attr {
AttributeType::AriaLabel(s) => return Some(s.as_str()),
_ => {}
}
}
for attr in self.attributes().as_ref() {
match attr {
AttributeType::Alt(s) | AttributeType::Title(s) => return Some(s.as_str()),
_ => {}
}
}
None
}
pub fn get_accessible_value(&self) -> Option<&str> {
for attr in self.attributes().as_ref() {
if let AttributeType::Value(s) = attr {
return Some(s.as_str());
}
}
None
}
pub fn get_placeholder(&self) -> Option<&str> {
for attr in self.attributes().as_ref() {
if let AttributeType::Placeholder(s) = attr {
return Some(s.as_str());
}
}
None
}
pub fn get_virtual_view_node(&mut self) -> Option<&mut VirtualViewNode> {
self.extra.as_mut()?.virtual_view.as_mut()
}
pub fn get_virtual_view_node_ref(&self) -> Option<&VirtualViewNode> {
self.extra.as_ref()?.virtual_view.as_ref()
}
pub fn get_render_image_callback_node<'a>(
&'a mut self,
) -> Option<(&'a mut CoreImageCallback, ImageRefHash)> {
match &mut self.node_type {
NodeType::Image(ref mut img) => {
let hash = image_ref_get_hash(img.as_ref());
img.as_mut().get_image_callback_mut().map(|r| (r, hash))
}
_ => None,
}
}
pub fn debug_print_start(
&self,
css_cache: &CssPropertyCache,
node_id: &NodeId,
node_state: &StyledNodeState,
) -> String {
let html_type = self.node_type.get_path();
let attributes_string = node_data_to_string(&self);
let style = css_cache.get_computed_css_style_string(&self, node_id, node_state);
format!(
"<{} data-az-node-id=\"{}\" {} {style}>",
html_type,
node_id.index(),
attributes_string,
style = if style.trim().is_empty() {
String::new()
} else {
format!("style=\"{style}\"")
}
)
}
pub fn debug_print_end(&self) -> String {
let html_type = self.node_type.get_path();
format!("</{}>", html_type)
}
}
impl crate::events::ActivationBehavior for NodeData {
fn has_activation_behavior(&self) -> bool {
NodeData::has_activation_behavior(self)
}
fn is_activatable(&self) -> bool {
NodeData::is_activatable(self)
}
}
impl crate::events::Focusable for NodeData {
fn get_tabindex(&self) -> Option<i32> {
self.get_effective_tabindex()
}
fn is_focusable(&self) -> bool {
NodeData::is_focusable(self)
}
fn is_naturally_focusable(&self) -> bool {
matches!(
self.node_type,
NodeType::A
| NodeType::Button
| NodeType::Input
| NodeType::Select
| NodeType::TextArea
)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub struct DomId {
pub inner: usize,
}
impl fmt::Display for DomId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.inner)
}
}
impl DomId {
pub const ROOT_ID: DomId = DomId { inner: 0 };
}
impl Default for DomId {
fn default() -> DomId {
DomId::ROOT_ID
}
}
impl_option!(
DomId,
OptionDomId,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_vec!(DomId, DomIdVec, DomIdVecDestructor, DomIdVecDestructorType, DomIdVecSlice, OptionDomId);
impl_vec_debug!(DomId, DomIdVec);
impl_vec_clone!(DomId, DomIdVec, DomIdVecDestructor);
impl_vec_partialeq!(DomId, DomIdVec);
impl_vec_partialord!(DomId, DomIdVec);
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct DomNodeId {
pub dom: DomId,
pub node: NodeHierarchyItemId,
}
impl_option!(
DomNodeId,
OptionDomNodeId,
[Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl DomNodeId {
pub const ROOT: DomNodeId = DomNodeId {
dom: DomId::ROOT_ID,
node: NodeHierarchyItemId::NONE,
};
}
#[repr(C)]
#[derive(PartialEq, Clone, PartialOrd)]
pub struct Dom {
pub root: NodeData,
pub children: DomVec,
pub css: azul_css::css::CssVec,
pub estimated_total_children: usize,
}
#[repr(C)]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct CssWithNodeId {
pub node_id: usize,
pub css: azul_css::css::Css,
}
impl_vec!(CssWithNodeId, CssWithNodeIdVec, CssWithNodeIdVecDestructor, CssWithNodeIdVecDestructorType, CssWithNodeIdVecSlice, OptionCssWithNodeId);
impl_option!(CssWithNodeId, OptionCssWithNodeId, copy = false, [Debug, Clone, PartialEq, PartialOrd]);
impl_vec_clone!(CssWithNodeId, CssWithNodeIdVec, CssWithNodeIdVecDestructor);
impl_vec_mut!(CssWithNodeId, CssWithNodeIdVec);
impl_vec_debug!(CssWithNodeId, CssWithNodeIdVec);
impl_vec_partialord!(CssWithNodeId, CssWithNodeIdVec);
impl_vec_partialeq!(CssWithNodeId, CssWithNodeIdVec);
#[repr(C)]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct FastDom {
pub node_hierarchy: crate::styled_dom::NodeHierarchyItemVec,
pub node_data: NodeDataVec,
pub css: CssWithNodeIdVec,
}
impl Eq for Dom {}
impl core::hash::Hash for Dom {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.root.hash(state);
self.children.hash(state);
self.estimated_total_children.hash(state);
}
}
impl Ord for Dom {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.root.cmp(&other.root)
.then_with(|| self.children.cmp(&other.children))
.then_with(|| self.estimated_total_children.cmp(&other.estimated_total_children))
}
}
impl_option!(
Dom,
OptionDom,
copy = false,
[Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
);
impl_vec!(Dom, DomVec, DomVecDestructor, DomVecDestructorType, DomVecSlice, OptionDom);
impl_vec_clone!(Dom, DomVec, DomVecDestructor);
impl_vec_mut!(Dom, DomVec);
impl_vec_debug!(Dom, DomVec);
impl_vec_partialord!(Dom, DomVec);
impl_vec_ord!(Dom, DomVec);
impl_vec_partialeq!(Dom, DomVec);
impl_vec_eq!(Dom, DomVec);
impl_vec_hash!(Dom, DomVec);
impl Dom {
#[inline(always)]
pub fn create_node(node_type: NodeType) -> Self {
Self {
root: NodeData::create_node(node_type),
children: Vec::new().into(),
css: Vec::new().into(),
estimated_total_children: 0,
}
}
#[inline(always)]
pub fn create_from_data(node_data: NodeData) -> Self {
Self {
root: node_data,
children: Vec::new().into(),
css: Vec::new().into(),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_html() -> Self {
Self {
root: NodeData::create_node(NodeType::Html),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_head() -> Self {
Self {
root: NodeData::create_node(NodeType::Head),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_body() -> Self {
Self {
root: NodeData::create_node(NodeType::Body),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_div() -> Self {
Self {
root: NodeData::create_node(NodeType::Div),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_article() -> Self {
Self {
root: NodeData::create_node(NodeType::Article),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_section() -> Self {
Self {
root: NodeData::create_node(NodeType::Section),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_nav() -> Self {
Self {
root: NodeData::create_node(NodeType::Nav),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_aside() -> Self {
Self {
root: NodeData::create_node(NodeType::Aside),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_header() -> Self {
Self {
root: NodeData::create_node(NodeType::Header),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_footer() -> Self {
Self {
root: NodeData::create_node(NodeType::Footer),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_main() -> Self {
Self {
root: NodeData::create_node(NodeType::Main),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_figure() -> Self {
Self {
root: NodeData::create_node(NodeType::Figure),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_figcaption() -> Self {
Self {
root: NodeData::create_node(NodeType::FigCaption),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_details_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Details),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_details(aria: SmallAriaInfo) -> Self {
Self::create_details_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_summary_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Summary),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_summary(aria: SmallAriaInfo) -> Self {
Self::create_summary_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline]
pub fn create_summary_with_text_no_a11y<S: Into<AzString>>(text: S) -> Self {
Self::create_summary_no_a11y().with_child(Self::create_text(text))
}
#[inline]
pub fn create_summary_with_text<S: Into<AzString>>(text: S, aria: SmallAriaInfo) -> Self {
Self::create_summary_with_text_no_a11y(text).with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_dialog_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Dialog),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_dialog(aria: DialogAriaInfo) -> Self {
Self::create_dialog_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_br() -> Self {
Self {
root: NodeData::create_node(NodeType::Br),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub fn create_text<S: Into<AzString>>(value: S) -> Self {
Self::create_node(NodeType::Text(BoxOrStatic::heap(value.into())))
}
#[inline(always)]
pub fn create_image(image: ImageRef) -> Self {
Self::create_node(NodeType::Image(BoxOrStatic::heap(image)))
}
#[inline(always)]
pub fn create_icon<S: Into<AzString>>(icon_name: S) -> Self {
Self::create_node(NodeType::Icon(BoxOrStatic::heap(icon_name.into())))
}
#[inline(always)]
pub fn create_virtual_view(data: RefAny, callback: impl Into<VirtualViewCallback>) -> Self {
Self::create_from_data(NodeData::create_virtual_view(data, callback))
}
#[inline(always)]
pub fn create_geolocation_probe(config: crate::geolocation::GeolocationProbeConfig) -> Self {
Self::create_node(NodeType::GeolocationProbe(config))
}
#[inline(always)]
pub const fn create_p() -> Self {
Self {
root: NodeData::create_node(NodeType::P),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_h1() -> Self {
Self {
root: NodeData::create_node(NodeType::H1),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_h1_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_h1().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_h2() -> Self {
Self {
root: NodeData::create_node(NodeType::H2),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_h2_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_h2().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_h3() -> Self {
Self {
root: NodeData::create_node(NodeType::H3),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_h3_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_h3().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_h4() -> Self {
Self {
root: NodeData::create_node(NodeType::H4),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_h4_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_h4().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_h5() -> Self {
Self {
root: NodeData::create_node(NodeType::H5),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_h5_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_h5().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_h6() -> Self {
Self {
root: NodeData::create_node(NodeType::H6),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_h6_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_h6().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_span() -> Self {
Self {
root: NodeData::create_node(NodeType::Span),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_span_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_span().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_strong() -> Self {
Self {
root: NodeData::create_node(NodeType::Strong),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_strong_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_strong().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_em() -> Self {
Self {
root: NodeData::create_node(NodeType::Em),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_em_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_em().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_code() -> Self {
Self::create_node(NodeType::Code)
}
#[inline]
pub fn create_code_with_text<S: Into<AzString>>(code: S) -> Self {
Self::create_code().with_child(Self::create_text(code))
}
#[inline(always)]
pub fn create_pre() -> Self {
Self::create_node(NodeType::Pre)
}
#[inline]
pub fn create_pre_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_pre().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_blockquote() -> Self {
Self::create_node(NodeType::BlockQuote)
}
#[inline]
pub fn create_blockquote_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_blockquote().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_cite() -> Self {
Self::create_node(NodeType::Cite)
}
#[inline]
pub fn create_cite_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_cite().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_abbr() -> Self {
Self::create_node(NodeType::Abbr)
}
#[inline]
pub fn create_abbr_with_title(abbr_text: AzString, title: AzString) -> Self {
Self::create_node(NodeType::Abbr)
.with_attribute(AttributeType::Title(title))
.with_child(Self::create_text(abbr_text))
}
#[inline(always)]
pub fn create_kbd() -> Self {
Self::create_node(NodeType::Kbd)
}
#[inline]
pub fn create_kbd_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_kbd().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_samp() -> Self {
Self::create_node(NodeType::Samp)
}
#[inline]
pub fn create_samp_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_samp().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_var() -> Self {
Self::create_node(NodeType::Var)
}
#[inline]
pub fn create_var_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_var().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_sub() -> Self {
Self::create_node(NodeType::Sub)
}
#[inline]
pub fn create_sub_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_sub().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_sup() -> Self {
Self::create_node(NodeType::Sup)
}
#[inline]
pub fn create_sup_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_sup().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_u() -> Self {
Self::create_node(NodeType::U)
}
#[inline]
pub fn create_u_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_u().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_s() -> Self {
Self::create_node(NodeType::S)
}
#[inline]
pub fn create_s_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_s().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_mark() -> Self {
Self::create_node(NodeType::Mark)
}
#[inline]
pub fn create_mark_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_mark().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_del() -> Self {
Self::create_node(NodeType::Del)
}
#[inline]
pub fn create_del_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_del().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_ins() -> Self {
Self::create_node(NodeType::Ins)
}
#[inline]
pub fn create_ins_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_ins().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_dfn() -> Self {
Self::create_node(NodeType::Dfn)
}
#[inline]
pub fn create_dfn_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_dfn().with_child(Self::create_text(text))
}
#[inline]
pub fn create_time(text: AzString, datetime: OptionString) -> Self {
let mut element = Self::create_node(NodeType::Time).with_child(Self::create_text(text));
if let OptionString::Some(dt) = datetime {
element = element.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "datetime".into(),
value: dt,
}));
}
element
}
#[inline(always)]
pub fn create_bdo() -> Self {
Self::create_node(NodeType::Bdo)
}
#[inline]
pub fn create_bdo_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_bdo().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_b() -> Self {
Self::create_node(NodeType::B)
}
#[inline]
pub fn create_b_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_b().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_i() -> Self {
Self::create_node(NodeType::I)
}
#[inline]
pub fn create_i_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_i().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_small() -> Self {
Self::create_node(NodeType::Small)
}
#[inline]
pub fn create_small_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_small().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_big() -> Self {
Self::create_node(NodeType::Big)
}
#[inline]
pub fn create_big_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_big().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_bdi() -> Self {
Self::create_node(NodeType::Bdi)
}
#[inline]
pub fn create_bdi_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_bdi().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_wbr() -> Self {
Self::create_node(NodeType::Wbr)
}
#[inline(always)]
pub fn create_ruby() -> Self {
Self::create_node(NodeType::Ruby)
}
#[inline(always)]
pub fn create_rt() -> Self {
Self::create_node(NodeType::Rt)
}
#[inline]
pub fn create_rt_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_rt().with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_rtc() -> Self {
Self::create_node(NodeType::Rtc)
}
#[inline(always)]
pub fn create_rp() -> Self {
Self::create_node(NodeType::Rp)
}
#[inline]
pub fn create_rp_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_rp().with_child(Self::create_text(text))
}
#[inline]
pub fn create_data(value: AzString) -> Self {
Self::create_node(NodeType::Data).with_attribute(AttributeType::Value(value))
}
#[inline]
pub fn create_data_with_text(value: AzString, text: AzString) -> Self {
Self::create_data(value).with_child(Self::create_text(text))
}
#[inline(always)]
pub fn create_dir() -> Self {
Self::create_node(NodeType::Dir)
}
#[inline(always)]
pub fn create_svg() -> Self {
Self::create_node(NodeType::Svg)
}
#[inline]
pub fn create_a_no_a11y(href: AzString, label: OptionString) -> Self {
let mut link = Self::create_node(NodeType::A).with_attribute(AttributeType::Href(href));
if let OptionString::Some(text) = label {
link = link.with_child(Self::create_text(text));
}
link
}
#[inline]
pub fn create_button_no_a11y(text: AzString) -> Self {
Self::create_node(NodeType::Button).with_child(Self::create_text(text))
}
#[inline]
pub fn create_label_no_a11y(for_id: AzString, text: AzString) -> Self {
Self::create_node(NodeType::Label)
.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "for".into(),
value: for_id,
}))
.with_child(Self::create_text(text))
}
#[inline]
pub fn create_input_no_a11y(input_type: AzString, name: AzString, label: AzString) -> Self {
Self::create_node(NodeType::Input)
.with_attribute(AttributeType::InputType(input_type))
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label))
}
#[inline]
pub fn create_textarea_no_a11y(name: AzString, label: AzString) -> Self {
Self::create_node(NodeType::TextArea)
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label))
}
#[inline]
pub fn create_select_no_a11y(name: AzString, label: AzString) -> Self {
Self::create_node(NodeType::Select)
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::AriaLabel(label))
}
#[inline]
pub fn create_option_no_a11y(value: AzString, text: AzString) -> Self {
Self::create_node(NodeType::SelectOption)
.with_attribute(AttributeType::Value(value))
.with_child(Self::create_text(text))
}
#[inline]
pub fn create_option(value: AzString, text: AzString, aria: SmallAriaInfo) -> Self {
Self::create_option_no_a11y(value, text).with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub fn create_ul() -> Self {
Self::create_node(NodeType::Ul)
}
#[inline(always)]
pub fn create_ol() -> Self {
Self::create_node(NodeType::Ol)
}
#[inline(always)]
pub fn create_li() -> Self {
Self::create_node(NodeType::Li)
}
#[inline(always)]
pub fn create_table_no_a11y() -> Self {
Self::create_node(NodeType::Table)
}
#[inline(always)]
pub fn create_caption() -> Self {
Self::create_node(NodeType::Caption)
}
#[inline(always)]
pub fn create_thead() -> Self {
Self::create_node(NodeType::THead)
}
#[inline(always)]
pub fn create_tbody() -> Self {
Self::create_node(NodeType::TBody)
}
#[inline(always)]
pub fn create_tfoot() -> Self {
Self::create_node(NodeType::TFoot)
}
#[inline(always)]
pub fn create_tr() -> Self {
Self::create_node(NodeType::Tr)
}
#[inline(always)]
pub fn create_th() -> Self {
Self::create_node(NodeType::Th)
}
#[inline(always)]
pub fn create_td() -> Self {
Self::create_node(NodeType::Td)
}
#[inline(always)]
pub fn create_form_no_a11y() -> Self {
Self::create_node(NodeType::Form)
}
#[inline]
pub fn create_form(aria: SmallAriaInfo) -> Self {
Self::create_form_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub fn create_fieldset_no_a11y() -> Self {
Self::create_node(NodeType::FieldSet)
}
#[inline]
pub fn create_fieldset(aria: SmallAriaInfo) -> Self {
Self::create_fieldset_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub fn create_legend_no_a11y() -> Self {
Self::create_node(NodeType::Legend)
}
#[inline]
pub fn create_legend(aria: SmallAriaInfo) -> Self {
Self::create_legend_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub fn create_hr() -> Self {
Self::create_node(NodeType::Hr)
}
#[inline(always)]
pub const fn create_address() -> Self {
Self {
root: NodeData::create_node(NodeType::Address),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_dl() -> Self {
Self {
root: NodeData::create_node(NodeType::Dl),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_dt() -> Self {
Self {
root: NodeData::create_node(NodeType::Dt),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_dd() -> Self {
Self {
root: NodeData::create_node(NodeType::Dd),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_colgroup() -> Self {
Self {
root: NodeData::create_node(NodeType::ColGroup),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_col(span: i32) -> Self {
Self::create_node(NodeType::Col).with_attribute(AttributeType::ColSpan(span))
}
#[inline]
pub fn create_optgroup_no_a11y(label: AzString) -> Self {
Self::create_node(NodeType::OptGroup).with_attribute(AttributeType::AriaLabel(label))
}
#[inline]
pub fn create_optgroup(label: AzString, aria: SmallAriaInfo) -> Self {
Self::create_optgroup_no_a11y(label).with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_q() -> Self {
Self {
root: NodeData::create_node(NodeType::Q),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_acronym() -> Self {
Self {
root: NodeData::create_node(NodeType::Acronym),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_acronym_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_acronym().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_menu_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Menu),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_menu(aria: SmallAriaInfo) -> Self {
Self::create_menu_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_menuitem_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::MenuItem),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_menuitem(aria: SmallAriaInfo) -> Self {
Self::create_menuitem_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline]
pub fn create_menuitem_with_text_no_a11y<S: Into<AzString>>(text: S) -> Self {
Self::create_menuitem_no_a11y().with_child(Self::create_text(text))
}
#[inline]
pub fn create_menuitem_with_text<S: Into<AzString>>(text: S, aria: SmallAriaInfo) -> Self {
Self::create_menuitem_with_text_no_a11y(text).with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_output_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Output),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_output(aria: SmallAriaInfo) -> Self {
Self::create_output_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline]
pub fn create_progress_no_a11y(value: f32, max: f32) -> Self {
Self::create_node(NodeType::Progress)
.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "value".into(),
value: value.to_string().into(),
}))
.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "max".into(),
value: max.to_string().into(),
}))
}
#[inline]
pub fn create_progress(aria: ProgressAriaInfo) -> Self {
let mut node = Self::create_node(NodeType::Progress);
if !aria.indeterminate {
if let azul_css::OptionF32::Some(v) = aria.current_value {
node = node.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "value".into(),
value: v.to_string().into(),
}));
}
}
if let azul_css::OptionF32::Some(m) = aria.max {
node = node.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "max".into(),
value: m.to_string().into(),
}));
}
node.with_accessibility_info(aria.to_full_info())
}
#[inline]
pub fn create_meter_no_a11y(value: f32, min: f32, max: f32) -> Self {
Self::create_node(NodeType::Meter)
.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "value".into(),
value: value.to_string().into(),
}))
.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "min".into(),
value: min.to_string().into(),
}))
.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "max".into(),
value: max.to_string().into(),
}))
}
#[inline]
pub fn create_meter(aria: MeterAriaInfo) -> Self {
let mut node = Self::create_meter_no_a11y(aria.current_value, aria.min, aria.max);
if let azul_css::OptionF32::Some(v) = aria.low {
node = node.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "low".into(),
value: v.to_string().into(),
}));
}
if let azul_css::OptionF32::Some(v) = aria.high {
node = node.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "high".into(),
value: v.to_string().into(),
}));
}
if let azul_css::OptionF32::Some(v) = aria.optimum {
node = node.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "optimum".into(),
value: v.to_string().into(),
}));
}
node.with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_datalist_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::DataList),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_datalist(aria: SmallAriaInfo) -> Self {
Self::create_datalist_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_canvas_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Canvas),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_canvas(aria: SmallAriaInfo) -> Self {
Self::create_canvas_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_object() -> Self {
Self {
root: NodeData::create_node(NodeType::Object),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_param(name: AzString, value: AzString) -> Self {
Self::create_node(NodeType::Param)
.with_attribute(AttributeType::Name(name))
.with_attribute(AttributeType::Value(value))
}
#[inline(always)]
pub const fn create_embed() -> Self {
Self {
root: NodeData::create_node(NodeType::Embed),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_audio_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Audio),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_audio(aria: SmallAriaInfo) -> Self {
Self::create_audio_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub const fn create_video_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Video),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_video(aria: SmallAriaInfo) -> Self {
Self::create_video_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline]
pub fn create_source(src: AzString, media_type: AzString) -> Self {
Self::create_node(NodeType::Source)
.with_attribute(AttributeType::Src(src))
.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "type".into(),
value: media_type,
}))
}
#[inline]
pub fn create_track(src: AzString, kind: AzString) -> Self {
Self::create_node(NodeType::Track)
.with_attribute(AttributeType::Src(src))
.with_attribute(AttributeType::Custom(AttributeNameValue {
attr_name: "kind".into(),
value: kind,
}))
}
#[inline(always)]
pub const fn create_map() -> Self {
Self {
root: NodeData::create_node(NodeType::Map),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_area_no_a11y() -> Self {
Self {
root: NodeData::create_node(NodeType::Area),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_area(aria: SmallAriaInfo) -> Self {
Self::create_area_no_a11y().with_accessibility_info(aria.to_full_info())
}
#[inline(always)]
pub fn create_title() -> Self {
Self::create_node(NodeType::Title)
}
#[inline]
pub fn create_title_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_title().with_child(Self::create_text(text))
}
#[inline(always)]
pub const fn create_meta() -> Self {
Self {
root: NodeData::create_node(NodeType::Meta),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_link() -> Self {
Self {
root: NodeData::create_node(NodeType::Link),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_script() -> Self {
Self {
root: NodeData::create_node(NodeType::Script),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline(always)]
pub const fn create_style() -> Self {
Self {
root: NodeData::create_node(NodeType::Style),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
}
}
#[inline]
pub fn create_style_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_style().with_child(Self::create_text(text))
}
#[inline]
pub fn create_base(href: AzString) -> Self {
Self::create_node(NodeType::Base).with_attribute(AttributeType::Href(href))
}
#[inline]
pub fn create_th_with_scope(scope: AzString, text: AzString) -> Self {
Self::create_node(NodeType::Th)
.with_attribute(AttributeType::Scope(scope))
.with_child(Self::create_text(text))
}
#[inline]
pub fn create_td_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_td().with_child(Self::create_text(text))
}
#[inline]
pub fn create_th_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_th().with_child(Self::create_text(text))
}
#[inline]
pub fn create_li_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_li().with_child(Self::create_text(text))
}
#[inline]
pub fn create_p_with_text<S: Into<AzString>>(text: S) -> Self {
Self::create_p().with_child(Self::create_text(text))
}
#[inline]
pub fn create_button<S: Into<AzString>>(text: S, aria: SmallAriaInfo) -> Self {
let mut btn = Self::create_button_no_a11y(text.into());
btn.root.set_accessibility_info(aria.to_full_info());
btn
}
#[inline]
pub fn create_a<S1: Into<AzString>, S2: Into<AzString>>(
href: S1,
text: S2,
aria: SmallAriaInfo,
) -> Self {
let mut link = Self::create_a_no_a11y(href.into(), OptionString::Some(text.into()));
link.root.set_accessibility_info(aria.to_full_info());
link
}
#[inline]
pub fn create_input<S1: Into<AzString>, S2: Into<AzString>, S3: Into<AzString>>(
input_type: S1,
name: S2,
label: S3,
aria: SmallAriaInfo,
) -> Self {
let mut input = Self::create_input_no_a11y(input_type.into(), name.into(), label.into());
input.root.set_accessibility_info(aria.to_full_info());
input
}
#[inline]
pub fn create_textarea<S1: Into<AzString>, S2: Into<AzString>>(
name: S1,
label: S2,
aria: SmallAriaInfo,
) -> Self {
let mut textarea = Self::create_textarea_no_a11y(name.into(), label.into());
textarea.root.set_accessibility_info(aria.to_full_info());
textarea
}
#[inline]
pub fn create_select<S1: Into<AzString>, S2: Into<AzString>>(
name: S1,
label: S2,
aria: SmallAriaInfo,
) -> Self {
let mut select = Self::create_select_no_a11y(name.into(), label.into());
select.root.set_accessibility_info(aria.to_full_info());
select
}
#[inline]
pub fn create_table<S: Into<AzString>>(caption: S, aria: SmallAriaInfo) -> Self {
let mut table = Self::create_table_no_a11y()
.with_child(Self::create_caption().with_child(Self::create_text(caption)));
table.root.set_accessibility_info(aria.to_full_info());
table
}
#[inline]
pub fn create_label<S1: Into<AzString>, S2: Into<AzString>>(
for_id: S1,
text: S2,
aria: SmallAriaInfo,
) -> Self {
let mut label = Self::create_label_no_a11y(for_id.into(), text.into());
label.root.set_accessibility_info(aria.to_full_info());
label
}
#[cfg(feature = "xml")]
pub fn from_xml<S: AsRef<str>>(xml_str: S) -> Self {
Self::create_text(format!(
"XML content loaded ({} bytes)",
xml_str.as_ref().len()
))
}
#[cfg(not(feature = "xml"))]
pub fn from_xml<S: AsRef<str>>(xml_str: S) -> Self {
Self::create_text(format!(
"XML parsing requires 'xml' feature ({} bytes)",
xml_str.as_ref().len()
))
}
#[inline(always)]
pub fn swap_with_default(&mut self) -> Self {
let mut s = Self {
root: NodeData::create_div(),
children: DomVec::from_const_slice(&[]),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children: 0,
};
mem::swap(&mut s, self);
s
}
#[inline]
pub fn add_child(&mut self, child: Dom) {
let estimated = child.estimated_total_children;
let mut v: DomVec = Vec::new().into();
mem::swap(&mut v, &mut self.children);
let mut v = v.into_library_owned_vec();
v.push(child);
self.children = v.into();
self.estimated_total_children += estimated + 1;
}
#[inline(always)]
pub fn set_children(&mut self, children: DomVec) {
let children_estimated = children
.iter()
.map(|s| s.estimated_total_children + 1)
.sum();
self.children = children;
self.estimated_total_children = children_estimated;
}
pub fn copy_except_for_root(&mut self) -> Self {
Self {
root: self.root.copy_special(),
children: self.children.clone(),
css: self.css.clone(),
estimated_total_children: self.estimated_total_children,
}
}
pub fn node_count(&self) -> usize {
self.estimated_total_children + 1
}
pub fn with_component_css(mut self, css: azul_css::css::Css) -> Self {
self.add_component_css(css);
self
}
pub fn add_component_css(&mut self, css: azul_css::css::Css) {
let mut v = Vec::new().into();
core::mem::swap(&mut v, &mut self.css);
let mut v: Vec<azul_css::css::Css> = v.into_library_owned_vec();
v.push(css);
self.css = v.into();
}
pub fn set_component_css(&mut self, css: azul_css::css::CssVec) {
self.css = css;
}
#[inline(always)]
pub fn with_children(mut self, children: DomVec) -> Self {
self.set_children(children);
self
}
#[inline(always)]
pub fn with_child(mut self, child: Self) -> Self {
self.add_child(child);
self
}
#[inline(always)]
pub fn with_node_type(mut self, node_type: NodeType) -> Self {
self.root.set_node_type(node_type);
self
}
#[inline(always)]
pub fn with_id(mut self, id: AzString) -> Self {
self.root.add_id(id);
self
}
#[inline(always)]
pub fn with_class(mut self, class: AzString) -> Self {
self.root.add_class(class);
self
}
#[inline(always)]
pub fn with_callback<C: Into<CoreCallback>>(
mut self,
event: EventFilter,
data: RefAny,
callback: C,
) -> Self {
self.root.add_callback(event, data, callback);
self
}
#[inline(always)]
pub fn with_css_property(mut self, prop: CssPropertyWithConditions) -> Self {
self.root.add_css_property(prop);
self
}
#[inline(always)]
pub fn add_css_property(&mut self, prop: CssPropertyWithConditions) {
self.root.add_css_property(prop);
}
#[inline(always)]
pub fn add_class(&mut self, class: AzString) {
self.root.add_class(class);
}
#[inline(always)]
pub fn add_callback<C: Into<CoreCallback>>(
&mut self,
event: EventFilter,
data: RefAny,
callback: C,
) {
self.root.add_callback(event, data, callback);
}
#[inline(always)]
pub fn set_tab_index(&mut self, tab_index: TabIndex) {
self.root.set_tab_index(tab_index);
}
#[inline(always)]
pub fn set_contenteditable(&mut self, contenteditable: bool) {
self.root.set_contenteditable(contenteditable);
}
#[inline(always)]
pub fn with_tab_index(mut self, tab_index: TabIndex) -> Self {
self.root.set_tab_index(tab_index);
self
}
#[inline(always)]
pub fn with_contenteditable(mut self, contenteditable: bool) -> Self {
self.root.set_contenteditable(contenteditable);
self
}
#[inline]
pub fn with_dataset(mut self, data: OptionRefAny) -> Self {
self.root.set_dataset(data);
self
}
#[inline(always)]
pub fn with_ids_and_classes(mut self, ids_and_classes: IdOrClassVec) -> Self {
self.root.set_ids_and_classes(ids_and_classes);
self
}
#[inline(always)]
pub fn with_attribute(mut self, attr: AttributeType) -> Self {
let mut attrs = self.root.attributes().clone();
let mut v = attrs.into_library_owned_vec();
v.push(attr);
self.root.set_attributes(v.into());
self
}
#[inline(always)]
pub fn with_attributes(mut self, attributes: AttributeTypeVec) -> Self {
self.root.set_attributes(attributes);
self
}
#[inline(always)]
pub fn with_callbacks(mut self, callbacks: CoreCallbackDataVec) -> Self {
self.root.callbacks = callbacks;
self
}
#[inline(always)]
pub fn with_css_props(mut self, css_props: CssPropertyWithConditionsVec) -> Self {
self.root.style = css_props.into();
self
}
#[inline(always)]
pub fn with_style(mut self, style: azul_css::css::Css) -> Self {
self.root.style = style;
self
}
#[inline]
pub fn with_key<K: core::hash::Hash>(mut self, key: K) -> Self {
self.root.set_key(key);
self
}
#[inline]
pub fn with_merge_callback<C: Into<DatasetMergeCallback>>(mut self, callback: C) -> Self {
self.root.set_merge_callback(callback);
self
}
pub fn set_css(&mut self, style: &str) {
let parsed = azul_css::css::Css::parse_inline(style);
let mut current: azul_css::css::CssRuleBlockVec = Vec::new().into();
mem::swap(&mut current, &mut self.root.style.rules);
let mut v = current.into_library_owned_vec();
v.extend(parsed.rules.into_library_owned_vec());
self.root.style.rules = v.into();
}
pub fn with_css(mut self, style: &str) -> Self {
self.set_css(style);
self
}
#[inline]
pub fn set_context_menu(&mut self, context_menu: Menu) {
self.root.set_context_menu(context_menu);
}
#[inline]
pub fn with_context_menu(mut self, context_menu: Menu) -> Self {
self.set_context_menu(context_menu);
self
}
#[inline]
pub fn set_menu_bar(&mut self, menu_bar: Menu) {
self.root.set_menu_bar(menu_bar);
}
#[inline]
pub fn with_menu_bar(mut self, menu_bar: Menu) -> Self {
self.set_menu_bar(menu_bar);
self
}
#[inline]
pub fn with_clip_mask(mut self, clip_mask: ImageMask) -> Self {
self.root.set_clip_mask(clip_mask);
self
}
#[inline]
pub fn with_svg_clip_path(mut self, clip: crate::svg::SvgMultiPolygon) -> Self {
self.root.set_svg_data(SvgNodeData::Path(clip));
self
}
#[inline]
pub fn with_svg_data(mut self, data: SvgNodeData) -> Self {
self.root.set_svg_data(data);
self
}
#[inline]
pub fn with_accessibility_info(mut self, accessibility_info: AccessibilityInfo) -> Self {
self.root.set_accessibility_info(accessibility_info);
self
}
pub fn fixup_children_estimated(&mut self) -> usize {
if self.children.is_empty() {
self.estimated_total_children = 0;
} else {
self.estimated_total_children = self
.children
.iter_mut()
.map(|s| s.fixup_children_estimated() + 1)
.sum();
}
return self.estimated_total_children;
}
}
impl core::iter::FromIterator<Dom> for Dom {
fn from_iter<I: IntoIterator<Item = Dom>>(iter: I) -> Self {
let mut estimated_total_children = 0;
let children = iter
.into_iter()
.map(|c| {
estimated_total_children += c.estimated_total_children + 1;
c
})
.collect::<Vec<Dom>>();
Dom {
root: NodeData::create_div(),
children: children.into(),
css: azul_css::css::CssVec::from_const_slice(&[]),
estimated_total_children,
}
}
}
impl fmt::Debug for Dom {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn print_dom(d: &Dom, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Dom {{\r\n")?;
write!(f, "\troot: {:#?}\r\n", d.root)?;
write!(
f,
"\testimated_total_children: {:#?}\r\n",
d.estimated_total_children
)?;
write!(f, "\tchildren: [\r\n")?;
for c in d.children.iter() {
print_dom(c, f)?;
}
write!(f, "\t]\r\n")?;
write!(f, "}}\r\n")?;
Ok(())
}
print_dom(self, f)
}
}