Recursive style deletion on Element removal#11
Conversation
| let Some(parent) = self.styles.get_mut(&parent_id) else { | ||
| return; | ||
| }; | ||
|
|
There was a problem hiding this comment.
Nice, I think we could add a
debug_assert!(parent.children.iter().any(|c| c.is_none()));Just to make sure we're not overriding any existing child ids.
a0e0c73 to
8e94995
Compare
Co-authored-by: Nixon <43715558+nixonyh@users.noreply.github.com>
nixonyh
left a comment
There was a problem hiding this comment.
Overall looks good! Thanks for writing the tests 😺 . I have added some comments that can be addressed in a separate PR.
| None | ||
| }; | ||
|
|
||
| // restore to old value |
There was a problem hiding this comment.
nit: I like comments to begin with capital and ends with fullstop xd (same goes to others too)
| /// Creates element `E`, applies the current style chain to it, | ||
| /// stores it, and returns its [`ElementId`]. | ||
| /// | ||
| /// Elements created with `add` dont own any styles, so their |
There was a problem hiding this comment.
nit: typo
| /// Elements created with `add` dont own any styles, so their | |
| /// Elements created with `add` don't own any styles, so their |
| if let Some(meta) = metas.remove(id) | ||
| && let Some(type_meta) = | ||
| type_metas.get_slot(meta.slot) | ||
| { | ||
| (type_meta.for_each_child_mut_fn)( | ||
| elements, | ||
| id, | ||
| &mut |child_id, elements| { | ||
| remove_recursive( | ||
| child_id, | ||
| metas, | ||
| type_metas, | ||
| elements, | ||
| id_generator, | ||
| ); | ||
| }, | ||
| ); | ||
|
|
||
| elements.dyn_remove_by_slot(meta.slot, id); | ||
| id_generator.recycle(*id); |
There was a problem hiding this comment.
Just noting that we might need some debug safe guard to make sure meta points to an actual element. Though, error like these shudn't happen anyway..
| /// Removes a committed style node and recycles its [`StyleId`]. | ||
| /// | ||
| /// Returns `true` if the node was present and removed. | ||
| pub fn delete(&mut self, id: &StyleId) -> bool { |
There was a problem hiding this comment.
Will need to remove this or make this private, it will disrupt the tree deletion flow.
| } | ||
|
|
||
| /// Recursively deletes a style and its children | ||
| pub fn delete_tree(&mut self, id: &StyleId) { |
There was a problem hiding this comment.
| pub fn delete_tree(&mut self, id: &StyleId) { | |
| pub fn remove(&mut self, id: &StyleId) { |
Probably rename this to remove and embed a fn remove_recursive similar to Elements.
| for c in children { | ||
| let Some(c) = c else { | ||
| continue; | ||
| }; |
There was a problem hiding this comment.
| for c in children { | |
| let Some(c) = c else { | |
| continue; | |
| }; | |
| for c in children.iter().filter_map(|c| c.as_ref()) { |
| /// Treat the style's children as a (sort-of) binary tree. | ||
| /// `children[0]` is one depth deeper (inner scope). | ||
| /// `children[1]` is same depth, subsequent style node. | ||
| children: [Option<StyleId>; 2], |
There was a problem hiding this comment.
I know this data structure was my suggestion, but after reading more, maybe this would be a better fit as they are both different thing after all.
| /// Treat the style's children as a (sort-of) binary tree. | |
| /// `children[0]` is one depth deeper (inner scope). | |
| /// `children[1]` is same depth, subsequent style node. | |
| children: [Option<StyleId>; 2], | |
| adjacent_child: Option<StyleId>, | |
| nested_child: Option<StyleId>, |
| let pre_commit_id = self.parent_style_id; | ||
|
|
||
| let mut element = self.create_element::<E>(true); | ||
|
|
||
| let pre_fn_id = self.parent_style_id; | ||
|
|
||
| // styleId from create_element | ||
| // else, current uncomited style if is None | ||
| let first_inner_style_id = self | ||
| .parent_style_id | ||
| .filter(|id| Some(*id) != pre_commit_id) | ||
| .unwrap_or_else(|| self.fynix.styles.current_id()); | ||
|
|
||
| f(&mut element, self); | ||
|
|
||
| // Restore parent style id from before the closure. | ||
| self.parent_style_id = parent_style_id; | ||
| // If self.parent_style_id has changed, that means a | ||
| // style has been committed inside the closure. | ||
| // It's ID would be that of `first_inner_style_id`, | ||
| // so our primary style is set to that. | ||
| let primary_style = if self.parent_style_id != pre_commit_id { | ||
| Some(first_inner_style_id) | ||
| } else { | ||
| None | ||
| }; | ||
|
|
||
| // restore to old value | ||
| self.parent_style_id = pre_fn_id; | ||
|
|
||
| self.fynix.elements.add(element) | ||
| let id = self.fynix.elements.add(element); | ||
|
|
||
| if let Some(style_id) = primary_style | ||
| && let Some(meta) = self.fynix.elements.metas.get_mut(&id) | ||
| { | ||
| meta.primary_style = Some(style_id); | ||
| } | ||
|
|
||
| id |
There was a problem hiding this comment.
Note: I still think we can do a better job here instead of relying on parent_style_id. Cuz it feels a little fragile (IMO) (?)
Closes #9
Closes #8