Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Expose view and taffy node from ViewId (#454)
* Expose view and taffy node from ViewId Rationale: Solving two problems here: 1. It is impossible to implement the same code as the default implementation of `View::layout()` outside of the `floem` crate, which limits what components in other crates can do to lay themselves out. 2. Most of the components in `floem::views` actually implement layout by manipulating the taffy tree (e.g, in `Label`, `self.id.taffy().borrow_mut().set_style(text_node, style);`. It is possible to implement at least the things I am trying to do right now simply by having access to the existing taffy NodeId for a View and using `ViewId::set_taffy_style`, so rather that the more extreme approach of exposing the whole taffy tree, I opted simply to add a call to get the node id - otherwise, the only access to it is from within a `layout` method which (prior to this patch at least) was inaccessible unless you could afford to give up the default layout behavior. I'm not entirely sure that just exposing the `view()` method is ideal here (though *something* is needed) - in my case I was debugging a panic from the `borrow_mut()` call in `View::layout()` which turned out to be that I was misusing the `ViewId` that gets passed in to the closure in `add_overlay()` as the id of the overlay component, which was already in use by the container for the overlay - so I wanted to reimplement the default behavior with logging to see exactly where things were going wrong. Attempting to use `try_borrow_mut()` instead to detect the source of the problem runs into lifetime problems between the erased lifetimes of `RefMut<'_, Box<dyn View>>` and `&mut LayoutCx<'_>`, which had to be resolved with some compiler trickery like this monstrosity (again, this is just debug code): ```rust fn layout_if_posible<'l, V: View + ?Sized + 'l>( view_cell: &Rc<RefCell<Box<V>>>, cx: &mut LayoutCx<'_>, ) -> Option<NodeId> { if let Ok(view) = view_cell.try_borrow_mut() { return Some(layout_view(view, cx)); } None } fn layout_view<'l, V: View + ?Sized + 'l>( mut v: RefMut<'l, Box<V>>, cx: &mut LayoutCx<'_>, ) -> NodeId { v.layout(cx) } ``` So it might actually be better to expose a method on `ViewId` that takes a closure with a signature like `with_view_id(&mut self, mut f : impl FnMut(&mut dyn View))` so users of the API are insulated from the erased lifetimes involved, and (perhaps?) use `try_borrow_mut` there and return a boolean (is there *ever* a **legitimate** case where there could be contention for the view, or was that only because I was abusing one id for two views?). At any rate, this patch is likely to be harmless as-is. * Don't expose `ViewId.view()` after all Since the problem I'm attempting to solve is to be able to override `layout()` in a `View` and still be able to use the default functionality, the ability to simply call that functionality as a standalone `pub fn` is probably enough to solve it (TBD, but very likely). * Export view::recursively_layout_view() to external callers
- Loading branch information