mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-10 20:29:33 -06:00
perf(doc,engine): rebuild a widget by removing its children in one pass (#1967)
This commit is contained in:
@@ -574,6 +574,19 @@ impl Document {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove every child of `id` with its subtree, in one pass over `id`'s child list (removing
|
||||
/// them one by one would search that list once per child).
|
||||
pub fn remove_children(&mut self, id: NodeId) -> DocResult<()> {
|
||||
let kids = std::mem::take(&mut self.get_mut(id)?.children);
|
||||
for c in kids {
|
||||
for d in self.subtree(c) {
|
||||
self.nodes.remove(&d);
|
||||
self.dirty.touch(d);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Whether sections may go in `parent`: a page or another section (never a frame or a group).
|
||||
pub fn takes_sections(&self, parent: NodeId) -> bool {
|
||||
self.node(parent).is_some_and(|p| p.is_page() || matches!(p.kind, NodeKind::Section { .. }))
|
||||
|
||||
@@ -846,3 +846,17 @@ fn the_colour_walker_visits_calculation_literals() {
|
||||
let ColorOperand::Literal { literal } = from else { panic!("literal operand") };
|
||||
assert_eq!(literal.a, 0.5, "the mix's stored literal was converted like every other colour");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_children_removes_every_subtree_and_keeps_the_parent() {
|
||||
let mut doc = Document::new("T");
|
||||
let page = doc.first_page().unwrap();
|
||||
let frame = doc.create(page, NodeKind::Frame, "F", 0.0, 0.0, 100.0, 100.0).unwrap();
|
||||
let inner = doc.create(frame, NodeKind::Frame, "Inner", 0.0, 0.0, 10.0, 10.0).unwrap();
|
||||
let leaf = doc.create(inner, NodeKind::Rectangle, "Leaf", 0.0, 0.0, 5.0, 5.0).unwrap();
|
||||
let other = doc.create(page, NodeKind::Rectangle, "Other", 0.0, 0.0, 5.0, 5.0).unwrap();
|
||||
doc.remove_children(frame).unwrap();
|
||||
assert!(doc.contains(frame) && doc.contains(other));
|
||||
assert!(!doc.contains(inner) && !doc.contains(leaf));
|
||||
assert!(doc.get(frame).unwrap().children.is_empty());
|
||||
}
|
||||
|
||||
@@ -243,9 +243,7 @@ fn build(s: &mut Session, plugin: &str, w: NodeId, r: &WidgetRender) -> Result<(
|
||||
if !is_widget(n) || n.plugin_data.get(PLUGIN).map(String::as_str) != Some(plugin) {
|
||||
return Err(bad(cmd, "the layer is no longer this plugin's widget"));
|
||||
}
|
||||
for c in n.children.clone() {
|
||||
doc.remove(c)?;
|
||||
}
|
||||
doc.remove_children(w)?;
|
||||
crate::cmd::props::apply(cmd, doc, w, &props(&r.root, true))?;
|
||||
let n = doc.get_mut(w)?;
|
||||
n.locked = false;
|
||||
|
||||
Reference in New Issue
Block a user