use super::*;
#[derive(Clone, Debug)]
pub struct NodeInspection {
pub path: String,
pub bounds: crate::Rect,
pub transform: crate::Transform,
pub filters: Vec<crate::Filter>,
pub clip_bounds: Option<crate::Rect>,
pub clipped: bool,
pub masked: bool,
}
impl Node {
pub fn inspect_with_context(
&self,
design_size: Size,
output_size: PixelSize,
limits: ValidationLimits,
drawing: &DrawContext,
) -> Result<Vec<NodeInspection>, ValidationError> {
let (root, scale) = output_size.mapping(design_size)?;
let mut context = drawing.clone().with_validation_limits(limits);
context.device_scale = scale;
let mut state = ValidationState::new(limits)?;
let planned = plan(self, "node", 1, &context, &mut state)?;
let mut output = Vec::new();
planned.inspect(root, &mut output)?;
Ok(output)
}
}
impl Plan {
fn inspect(
&self,
parent: Transform,
output: &mut Vec<NodeInspection>,
) -> Result<(), ValidationError> {
let transform = self.transform.then(parent);
let clip_bounds = self
.rect_clip
.map(|clip| mapped_bounds(clip.bounds, clip.transform.then(transform), &self.path))
.transpose()?;
output.push(NodeInspection {
path: self.path.clone(),
bounds: self.visual_bounds(parent)?.rect(&self.path)?,
transform,
filters: self.filters.clone(),
clip_bounds,
clipped: self.rect_clip.is_some() || self.clip.is_some() || self.shape_clip.is_some(),
masked: self.mask.is_some(),
});
if let Content::Children(children) = &self.content {
for child in children {
child.inspect(transform, output)?;
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Color, NodeModifiers, Rect};
#[test]
fn inspection_uses_compiled_layout_names_mapping_and_order() {
let node = Node::group([
Node::from(Rect::new(0.0, 0.0, 10.0, 10.0).fill(Color::WHITE))
.named("front")
.z_index(2),
Node::from(Rect::new(0.0, 0.0, 5.0, 5.0).fill(Color::WHITE)).named("back"),
])
.translate(3.0, 4.0);
let inspect = node
.inspect_with_context(
Size::new(20.0, 20.0),
PixelSize::new(40, 40),
ValidationLimits::default(),
&DrawContext::default(),
)
.unwrap();
assert_eq!(inspect.len(), 3);
assert!(inspect[1].path.contains("back"));
assert!(inspect[2].path.contains("front"));
assert_eq!(inspect[2].bounds, Rect::new(6.0, 8.0, 26.0, 28.0));
assert!(
node.inspect_with_context(
Size::new(20.0, 20.0),
PixelSize::new(40, 40),
ValidationLimits {
max_nodes: 1,
..ValidationLimits::default()
},
&DrawContext::default()
)
.is_err()
);
}
}