1use std::cell::{Cell, Ref, RefCell, RefMut};
2use std::collections::HashMap;
3use std::rc::Rc;
4
5use cranpose_core::{
6 Composer, NodeError, NodeId, Phase, SlotId, SlotTable, SlotsHost, SubcomposeState,
7};
8
9use crate::layout::MeasuredNode;
10use crate::modifier::{
11 collect_modifier_slices_into, Modifier, ModifierChainHandle, ModifierNodeSlices, Point,
12 ResolvedModifiers, Size,
13};
14use crate::widgets::nodes::{
15 allocate_virtual_node_id, is_virtual_node, register_layout_node, LayoutNode, LayoutState,
16};
17
18use cranpose_foundation::{InvalidationKind, ModifierInvalidation, NodeCapabilities};
19
20pub use cranpose_ui_layout::{Constraints, MeasureResult, Placement};
21
22#[derive(Clone, Copy, Debug)]
27pub struct SubcomposeChild {
28 node_id: NodeId,
29 measured_size: Option<Size>,
32}
33
34impl SubcomposeChild {
35 pub fn new(node_id: NodeId) -> Self {
36 Self {
37 node_id,
38 measured_size: None,
39 }
40 }
41
42 pub fn with_size(node_id: NodeId, size: Size) -> Self {
44 Self {
45 node_id,
46 measured_size: Some(size),
47 }
48 }
49
50 pub fn node_id(&self) -> NodeId {
51 self.node_id
52 }
53
54 pub fn size(&self) -> Size {
59 self.measured_size.unwrap_or(Size {
60 width: 0.0,
61 height: 0.0,
62 })
63 }
64
65 pub fn width(&self) -> f32 {
67 self.size().width
68 }
69
70 pub fn height(&self) -> f32 {
72 self.size().height
73 }
74
75 pub fn set_size(&mut self, size: Size) {
77 self.measured_size = Some(size);
78 }
79}
80
81impl PartialEq for SubcomposeChild {
82 fn eq(&self, other: &Self) -> bool {
83 self.node_id == other.node_id
84 }
85}
86
87pub type SubcomposePlaceable = cranpose_ui_layout::Placeable;
93
94pub trait SubcomposeLayoutScope {
96 fn constraints(&self) -> Constraints;
97
98 fn layout<I>(&mut self, width: f32, height: f32, placements: I) -> MeasureResult
99 where
100 I: IntoIterator<Item = Placement>,
101 {
102 MeasureResult::new(Size { width, height }, placements.into_iter().collect())
103 }
104}
105
106pub trait SubcomposeMeasureScope: SubcomposeLayoutScope {
108 fn subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<SubcomposeChild>
109 where
110 Content: FnMut() + 'static;
111
112 fn measure(&mut self, child: SubcomposeChild, constraints: Constraints) -> SubcomposePlaceable;
114
115 fn node_has_no_parent(&self, node_id: NodeId) -> bool;
118}
119
120pub struct SubcomposeMeasureScopeImpl<'a> {
122 composer: Composer,
123 state: &'a mut SubcomposeState,
124 constraints: Constraints,
125 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
126 error: &'a RefCell<Option<NodeError>>,
127 parent_handle: SubcomposeLayoutNodeHandle,
128 root_id: NodeId,
129 placement_scratch: Vec<Placement>,
130}
131
132struct SubcomposeMeasureScopeInit<'a> {
133 composer: Composer,
134 state: &'a mut SubcomposeState,
135 constraints: Constraints,
136 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
137 error: &'a RefCell<Option<NodeError>>,
138 parent_handle: SubcomposeLayoutNodeHandle,
139 root_id: NodeId,
140 placement_scratch: Vec<Placement>,
141}
142
143impl<'a> SubcomposeMeasureScopeImpl<'a> {
144 fn new(init: SubcomposeMeasureScopeInit<'a>) -> Self {
145 Self {
146 composer: init.composer,
147 state: init.state,
148 constraints: init.constraints,
149 measurer: init.measurer,
150 error: init.error,
151 parent_handle: init.parent_handle,
152 root_id: init.root_id,
153 placement_scratch: init.placement_scratch,
154 }
155 }
156
157 fn into_placement_scratch(self) -> Vec<Placement> {
158 self.placement_scratch
159 }
160
161 pub(crate) fn layout_with_placement_builder(
162 &mut self,
163 width: f32,
164 height: f32,
165 build: impl FnOnce(&mut Vec<Placement>),
166 ) -> MeasureResult {
167 self.placement_scratch.clear();
168 build(&mut self.placement_scratch);
169 MeasureResult::new(
170 Size { width, height },
171 std::mem::take(&mut self.placement_scratch),
172 )
173 }
174
175 fn record_error(&self, err: NodeError) {
176 let mut slot = self.error.borrow_mut();
177 if slot.is_none() {
178 eprintln!("[SubcomposeLayout] Error suppressed: {:?}", err);
179 *slot = Some(err);
180 }
181 }
182
183 fn perform_subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<NodeId>
184 where
185 Content: FnMut() + 'static,
186 {
187 let content_holder = self.state.callback_holder(slot_id);
188 content_holder.update(content);
189 let mut inner = self.parent_handle.inner.borrow_mut();
190
191 let (virtual_node_id, is_reused) =
193 if let Some(node_id) = self.state.take_node_from_reusables(slot_id) {
194 (node_id, true)
195 } else {
196 let id = allocate_virtual_node_id();
197 let node = LayoutNode::new_virtual();
198 if let Err(e) = self
202 .composer
203 .register_virtual_node(id, Box::new(node.clone()))
204 {
205 eprintln!(
206 "[Subcompose] Failed to register virtual node {}: {:?}",
207 id, e
208 );
209 }
210 register_layout_node(id, &node);
211
212 inner.virtual_nodes.insert(id, Rc::new(node));
213 inner.children.push(id);
214 (id, false)
215 };
216
217 self.composer.record_subcompose_child(virtual_node_id);
220
221 if let Some(v_node) = inner.virtual_nodes.get(&virtual_node_id) {
224 v_node.set_parent(self.root_id);
225 }
226
227 drop(inner);
228
229 let _ = self
230 .composer
231 .with_node_mut::<LayoutNode, _>(virtual_node_id, |node| {
232 node.set_parent(self.root_id);
233 });
234
235 if is_reused {
239 self.composer.clear_node_children(virtual_node_id);
240 }
241
242 let slot_host = self.state.get_or_create_slots(slot_id);
243 let holder_for_slot = content_holder.clone();
244 let scopes = self
245 .composer
246 .subcompose_slot(&slot_host, Some(virtual_node_id), move |_| {
247 compose_subcompose_slot_content(holder_for_slot.clone());
248 })
249 .map(|(_, scopes)| scopes)
250 .unwrap_or_default();
251
252 self.state
253 .register_active(slot_id, &[virtual_node_id], &scopes);
254
255 self.composer.get_node_children(virtual_node_id).to_vec()
259 }
260}
261
262impl<'a> SubcomposeLayoutScope for SubcomposeMeasureScopeImpl<'a> {
263 fn constraints(&self) -> Constraints {
264 self.constraints
265 }
266
267 fn layout<I>(&mut self, width: f32, height: f32, placements: I) -> MeasureResult
268 where
269 I: IntoIterator<Item = Placement>,
270 {
271 self.layout_with_placement_builder(width, height, |scratch| {
272 scratch.extend(placements);
273 })
274 }
275}
276
277impl<'a> SubcomposeMeasureScope for SubcomposeMeasureScopeImpl<'a> {
278 fn subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<SubcomposeChild>
279 where
280 Content: FnMut() + 'static,
281 {
282 let nodes = self.perform_subcompose(slot_id, content);
283 nodes.into_iter().map(SubcomposeChild::new).collect()
284 }
285
286 fn measure(&mut self, child: SubcomposeChild, constraints: Constraints) -> SubcomposePlaceable {
287 if self.error.borrow().is_some() {
288 return SubcomposePlaceable::value(0.0, 0.0, child.node_id);
290 }
291
292 if let Err(err) = self.composer.apply_pending_commands() {
293 self.record_error(err);
294 return SubcomposePlaceable::value(0.0, 0.0, child.node_id);
295 }
296
297 let size = (self.measurer)(child.node_id, constraints);
298 SubcomposePlaceable::value(size.width, size.height, child.node_id)
299 }
300
301 fn node_has_no_parent(&self, node_id: NodeId) -> bool {
302 self.composer.node_has_no_parent(node_id)
303 }
304}
305
306impl<'a> SubcomposeMeasureScopeImpl<'a> {
307 pub fn subcompose_with_size<Content, F>(
312 &mut self,
313 slot_id: SlotId,
314 content: Content,
315 estimate_size: F,
316 ) -> Vec<SubcomposeChild>
317 where
318 Content: FnMut() + 'static,
319 F: Fn(usize) -> Size,
320 {
321 let nodes = self.perform_subcompose(slot_id, content);
322 nodes
323 .into_iter()
324 .enumerate()
325 .map(|(i, node_id)| SubcomposeChild::with_size(node_id, estimate_size(i)))
326 .collect()
327 }
328
329 pub fn active_slots_count(&self) -> usize {
333 self.state.active_slots_count()
334 }
335
336 pub fn reusable_slots_count(&self) -> usize {
340 self.state.reusable_slots_count()
341 }
342
343 pub fn register_content_type(&mut self, slot_id: SlotId, content_type: u64) {
349 self.state.register_content_type(slot_id, content_type);
350 }
351
352 pub fn update_content_type(&mut self, slot_id: SlotId, content_type: Option<u64>) {
358 self.state.update_content_type(slot_id, content_type);
359 }
360
361 pub fn was_last_slot_reused(&self) -> Option<bool> {
369 self.state.was_last_slot_reused()
370 }
371}
372
373fn compose_subcompose_slot_content(holder: cranpose_core::CallbackHolder) {
374 cranpose_core::with_current_composer(|composer| {
375 let holder_for_recompose = holder.clone();
376 composer.set_recranpose_callback(move |_composer| {
377 compose_subcompose_slot_content(holder_for_recompose.clone());
378 });
379 });
380
381 let invoke = holder.clone_rc();
382 invoke();
383}
384
385pub type MeasurePolicy =
387 dyn for<'scope> Fn(&mut SubcomposeMeasureScopeImpl<'scope>, Constraints) -> MeasureResult;
388
389pub struct SubcomposeLayoutNode {
391 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
392 parent: Cell<Option<NodeId>>,
394 id: Cell<Option<NodeId>>,
396 needs_measure: Cell<bool>,
398 needs_layout: Cell<bool>,
399 needs_semantics: Cell<bool>,
400 needs_redraw: Cell<bool>,
401 needs_pointer_pass: Cell<bool>,
402 needs_focus_sync: Cell<bool>,
403 virtual_children_count: Cell<usize>,
404 layout_state: RefCell<LayoutState>,
406 modifier_slices_snapshot: RefCell<Rc<ModifierNodeSlices>>,
407 modifier_slices_dirty: Cell<bool>,
408}
409
410impl SubcomposeLayoutNode {
411 pub fn new(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
412 let inner = Rc::new(RefCell::new(SubcomposeLayoutNodeInner::new(measure_policy)));
413 let node = Self {
414 inner,
415 parent: Cell::new(None),
416 id: Cell::new(None),
417 needs_measure: Cell::new(true),
418 needs_layout: Cell::new(true),
419 needs_semantics: Cell::new(true),
420 needs_redraw: Cell::new(true),
421 needs_pointer_pass: Cell::new(false),
422 needs_focus_sync: Cell::new(false),
423 virtual_children_count: Cell::new(0),
424 layout_state: RefCell::new(LayoutState::default()),
425 modifier_slices_snapshot: RefCell::new(Rc::default()),
426 modifier_slices_dirty: Cell::new(true),
427 };
428 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
431 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
432 node.update_modifier_slices_cache();
433 node
434 }
435
436 pub fn with_content_type_policy(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
442 let mut inner_data = SubcomposeLayoutNodeInner::new(measure_policy);
443 inner_data
444 .state
445 .set_policy(Box::new(cranpose_core::ContentTypeReusePolicy::new()));
446 let inner = Rc::new(RefCell::new(inner_data));
447 let node = Self {
448 inner,
449 parent: Cell::new(None),
450 id: Cell::new(None),
451 needs_measure: Cell::new(true),
452 needs_layout: Cell::new(true),
453 needs_semantics: Cell::new(true),
454 needs_redraw: Cell::new(true),
455 needs_pointer_pass: Cell::new(false),
456 needs_focus_sync: Cell::new(false),
457 virtual_children_count: Cell::new(0),
458 layout_state: RefCell::new(LayoutState::default()),
459 modifier_slices_snapshot: RefCell::new(Rc::default()),
460 modifier_slices_dirty: Cell::new(true),
461 };
462 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
465 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
466 node.update_modifier_slices_cache();
467 node
468 }
469
470 pub fn handle(&self) -> SubcomposeLayoutNodeHandle {
471 SubcomposeLayoutNodeHandle {
472 inner: Rc::clone(&self.inner),
473 }
474 }
475
476 #[doc(hidden)]
477 pub fn debug_scope_ids_by_slot(&self) -> Vec<(u64, Vec<usize>)> {
478 self.inner.borrow().state.debug_scope_ids_by_slot()
479 }
480
481 #[doc(hidden)]
482 pub fn debug_slot_table_for_slot(
483 &self,
484 slot_id: cranpose_core::SlotId,
485 ) -> Option<Vec<cranpose_core::SlotDebugEntry>> {
486 self.inner.borrow().state.debug_slot_table_for_slot(slot_id)
487 }
488
489 #[doc(hidden)]
490 pub fn debug_slot_table_groups_for_slot(
491 &self,
492 slot_id: cranpose_core::SlotId,
493 ) -> Option<Vec<cranpose_core::subcompose::DebugSlotGroup>> {
494 self.inner
495 .borrow()
496 .state
497 .debug_slot_table_groups_for_slot(slot_id)
498 }
499
500 pub fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
501 let mut inner = self.inner.borrow_mut();
502 if Rc::ptr_eq(&inner.measure_policy, &policy) {
503 return;
504 }
505 inner.set_measure_policy(policy);
506 drop(inner);
507 self.invalidate_subcomposition();
508 }
509
510 pub fn set_modifier(&mut self, modifier: Modifier) {
511 let prev_caps = self.modifier_capabilities();
513 let (invalidations, modifier_changed) = {
515 let mut inner = self.inner.borrow_mut();
516 inner.set_modifier_collect(modifier)
517 };
518 self.dispatch_modifier_invalidations(&invalidations, prev_caps);
521 self.update_modifier_slices_cache();
522 if modifier_changed {
523 self.request_semantics_update();
524 }
525 }
526
527 fn update_modifier_slices_cache(&self) {
529 let inner = self.inner.borrow();
530 let mut snapshot = self.modifier_slices_snapshot.borrow_mut();
531 collect_modifier_slices_into(inner.modifier_chain.chain(), Rc::make_mut(&mut snapshot));
532 self.modifier_slices_dirty.set(false);
533 }
534
535 pub(crate) fn mark_modifier_slices_dirty(&self) {
536 self.modifier_slices_dirty.set(true);
537 }
538
539 pub fn set_debug_modifiers(&mut self, enabled: bool) {
540 self.inner.borrow_mut().set_debug_modifiers(enabled);
541 }
542
543 pub fn modifier(&self) -> Modifier {
544 self.handle().modifier()
545 }
546
547 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
548 self.inner.borrow().resolved_modifiers
549 }
550
551 pub fn layout_state(&self) -> LayoutState {
553 self.layout_state.borrow().clone()
554 }
555
556 pub fn set_position(&self, position: Point) {
558 let mut state = self.layout_state.borrow_mut();
559 state.position = position;
560 state.is_placed = true;
561 }
562
563 pub fn set_measured_size(&self, size: Size) {
565 let mut state = self.layout_state.borrow_mut();
566 state.size = size;
567 }
568
569 pub fn clear_placed(&self) {
571 self.layout_state.borrow_mut().is_placed = false;
572 }
573
574 pub fn modifier_slices_snapshot(&self) -> Rc<ModifierNodeSlices> {
576 if self.modifier_slices_dirty.get() {
577 self.update_modifier_slices_cache();
578 }
579 self.modifier_slices_snapshot.borrow().clone()
580 }
581
582 pub fn state(&self) -> Ref<'_, SubcomposeState> {
583 Ref::map(self.inner.borrow(), |inner| &inner.state)
584 }
585
586 pub fn state_mut(&self) -> RefMut<'_, SubcomposeState> {
587 RefMut::map(self.inner.borrow_mut(), |inner| &mut inner.state)
588 }
589
590 pub fn invalidate_subcomposition(&self) {
591 self.inner.borrow().state.invalidate_scopes();
592 self.mark_needs_measure();
593 if let Some(id) = self.id.get() {
594 cranpose_core::bubble_measure_dirty_in_composer(id);
595 }
596 }
597
598 pub fn request_measure_recompose(&self) {
599 self.mark_needs_measure();
600 if let Some(id) = self.id.get() {
601 cranpose_core::bubble_measure_dirty_in_composer(id);
602 }
603 }
604
605 pub fn active_children(&self) -> Vec<NodeId> {
606 current_subcompose_children(&self.inner.borrow())
607 }
608
609 pub fn mark_needs_measure(&self) {
611 self.needs_measure.set(true);
612 self.needs_layout.set(true);
613 }
614
615 pub fn mark_needs_layout_flag(&self) {
617 self.needs_layout.set(true);
618 }
619
620 pub fn mark_needs_redraw(&self) {
622 self.needs_redraw.set(true);
623 if let Some(id) = self.id.get() {
624 crate::schedule_draw_repass(id);
625 }
626 crate::request_render_invalidation();
627 }
628
629 pub fn needs_measure(&self) -> bool {
631 self.needs_measure.get()
632 }
633
634 pub(crate) fn clear_needs_measure(&self) {
635 self.needs_measure.set(false);
636 }
637
638 pub(crate) fn clear_needs_layout(&self) {
639 self.needs_layout.set(false);
640 }
641
642 pub fn mark_needs_semantics(&self) {
644 self.needs_semantics.set(true);
645 }
646
647 pub fn needs_semantics_flag(&self) -> bool {
649 self.needs_semantics.get()
650 }
651
652 pub(crate) fn clear_needs_semantics(&self) {
653 self.needs_semantics.set(false);
654 }
655
656 #[cfg(test)]
657 pub(crate) fn clear_needs_semantics_for_tests(&self) {
658 self.clear_needs_semantics();
659 }
660
661 pub fn needs_redraw(&self) -> bool {
663 self.needs_redraw.get()
664 }
665
666 pub fn clear_needs_redraw(&self) {
667 self.needs_redraw.set(false);
668 }
669
670 pub fn mark_needs_pointer_pass(&self) {
672 self.needs_pointer_pass.set(true);
673 }
674
675 pub fn needs_pointer_pass(&self) -> bool {
677 self.needs_pointer_pass.get()
678 }
679
680 pub fn clear_needs_pointer_pass(&self) {
682 self.needs_pointer_pass.set(false);
683 }
684
685 pub fn mark_needs_focus_sync(&self) {
687 self.needs_focus_sync.set(true);
688 }
689
690 pub fn needs_focus_sync(&self) -> bool {
692 self.needs_focus_sync.get()
693 }
694
695 pub fn clear_needs_focus_sync(&self) {
697 self.needs_focus_sync.set(false);
698 }
699
700 fn request_semantics_update(&self) {
701 let already_dirty = self.needs_semantics.replace(true);
702 if already_dirty {
703 return;
704 }
705
706 if let Some(id) = self.id.get() {
707 cranpose_core::queue_semantics_invalidation(id);
708 }
709 }
710
711 pub fn modifier_capabilities(&self) -> NodeCapabilities {
713 self.inner.borrow().modifier_capabilities
714 }
715
716 pub fn has_layout_modifier_nodes(&self) -> bool {
717 self.modifier_capabilities()
718 .contains(NodeCapabilities::LAYOUT)
719 }
720
721 pub fn has_draw_modifier_nodes(&self) -> bool {
722 self.modifier_capabilities()
723 .contains(NodeCapabilities::DRAW)
724 }
725
726 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
727 self.modifier_capabilities()
728 .contains(NodeCapabilities::POINTER_INPUT)
729 }
730
731 pub fn has_semantics_modifier_nodes(&self) -> bool {
732 self.modifier_capabilities()
733 .contains(NodeCapabilities::SEMANTICS)
734 }
735
736 pub fn has_focus_modifier_nodes(&self) -> bool {
737 self.modifier_capabilities()
738 .contains(NodeCapabilities::FOCUS)
739 }
740
741 fn dispatch_modifier_invalidations(
748 &self,
749 invalidations: &[ModifierInvalidation],
750 prev_caps: NodeCapabilities,
751 ) {
752 let curr_caps = self.modifier_capabilities();
753 for invalidation in invalidations {
754 self.modifier_slices_dirty.set(true);
755 match invalidation.kind() {
756 InvalidationKind::Layout => {
757 if curr_caps.contains(NodeCapabilities::LAYOUT)
758 || prev_caps.contains(NodeCapabilities::LAYOUT)
759 {
760 self.mark_needs_measure();
761 }
762 }
763 InvalidationKind::Draw => {
764 if curr_caps.contains(NodeCapabilities::DRAW)
765 || prev_caps.contains(NodeCapabilities::DRAW)
766 {
767 self.mark_needs_redraw();
768 }
769 }
770 InvalidationKind::PointerInput => {
771 if curr_caps.contains(NodeCapabilities::POINTER_INPUT)
772 || prev_caps.contains(NodeCapabilities::POINTER_INPUT)
773 {
774 self.mark_needs_pointer_pass();
775 crate::request_pointer_invalidation();
776 if let Some(id) = self.id.get() {
778 crate::schedule_pointer_repass(id);
779 }
780 }
781 }
782 InvalidationKind::Semantics => {
783 self.request_semantics_update();
784 }
785 InvalidationKind::Focus => {
786 if curr_caps.contains(NodeCapabilities::FOCUS)
787 || prev_caps.contains(NodeCapabilities::FOCUS)
788 {
789 self.mark_needs_focus_sync();
790 crate::request_focus_invalidation();
791 if let Some(id) = self.id.get() {
793 crate::schedule_focus_invalidation(id);
794 }
795 }
796 }
797 }
798 }
799 }
800}
801
802impl cranpose_core::Node for SubcomposeLayoutNode {
803 fn mount(&mut self) {
804 let mut inner = self.inner.borrow_mut();
805 let (chain, mut context) = inner.modifier_chain.chain_and_context_mut();
806 chain.repair_chain();
807 chain.attach_nodes(&mut *context);
808 }
809
810 fn unmount(&mut self) {
811 self.inner
812 .borrow_mut()
813 .modifier_chain
814 .chain_mut()
815 .detach_nodes();
816 }
817
818 fn insert_child(&mut self, child: NodeId) {
819 let mut inner = self.inner.borrow_mut();
820 if inner.children.contains(&child) {
821 return;
822 }
823 if is_virtual_node(child) {
824 let count = self.virtual_children_count.get();
825 self.virtual_children_count.set(count + 1);
826 }
827 inner.children.push(child);
828 }
829
830 fn remove_child(&mut self, child: NodeId) {
831 let mut inner = self.inner.borrow_mut();
832 let before = inner.children.len();
833 inner.children.retain(|&id| id != child);
834 if inner.children.len() < before && is_virtual_node(child) {
835 let count = self.virtual_children_count.get();
836 if count > 0 {
837 self.virtual_children_count.set(count - 1);
838 }
839 }
840 }
841
842 fn move_child(&mut self, from: usize, to: usize) {
843 let mut inner = self.inner.borrow_mut();
844 if from == to || from >= inner.children.len() {
845 return;
846 }
847 let child = inner.children.remove(from);
848 let target = to.min(inner.children.len());
849 inner.children.insert(target, child);
850 }
851
852 fn update_children(&mut self, children: &[NodeId]) {
853 let mut inner = self.inner.borrow_mut();
854 inner.children.clear();
855 inner.children.extend_from_slice(children);
856 }
857
858 fn children(&self) -> Vec<NodeId> {
859 current_subcompose_children(&self.inner.borrow())
860 }
861
862 fn set_node_id(&mut self, id: NodeId) {
863 self.id.set(Some(id));
864 self.inner.borrow_mut().modifier_chain.set_node_id(Some(id));
865 self.update_modifier_slices_cache();
866 }
867
868 fn on_attached_to_parent(&mut self, parent: NodeId) {
869 self.parent.set(Some(parent));
870 }
871
872 fn on_removed_from_parent(&mut self) {
873 self.parent.set(None);
874 }
875
876 fn parent(&self) -> Option<NodeId> {
877 self.parent.get()
878 }
879
880 fn mark_needs_layout(&self) {
881 self.needs_layout.set(true);
882 }
883
884 fn needs_layout(&self) -> bool {
885 self.needs_layout.get()
886 }
887
888 fn mark_needs_measure(&self) {
889 self.needs_measure.set(true);
890 self.needs_layout.set(true); }
892
893 fn needs_measure(&self) -> bool {
894 self.needs_measure.get()
895 }
896
897 fn mark_needs_semantics(&self) {
898 self.needs_semantics.set(true);
899 }
900
901 fn needs_semantics(&self) -> bool {
902 self.needs_semantics.get()
903 }
904
905 fn set_parent_for_bubbling(&mut self, parent: NodeId) {
907 self.parent.set(Some(parent));
908 }
909}
910
911#[derive(Clone)]
912pub struct SubcomposeLayoutNodeHandle {
913 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
914}
915
916impl SubcomposeLayoutNodeHandle {
917 pub(crate) fn measured_children_scratch(
918 &self,
919 ) -> Rc<RefCell<HashMap<NodeId, Rc<MeasuredNode>>>> {
920 let scratch = {
921 let inner = self.inner.borrow();
922 Rc::clone(&inner.measured_children_scratch)
923 };
924 scratch.borrow_mut().clear();
925 scratch
926 }
927
928 pub fn modifier(&self) -> Modifier {
929 self.inner.borrow().modifier.clone()
930 }
931
932 pub fn layout_properties(&self) -> crate::modifier::LayoutProperties {
933 self.resolved_modifiers().layout_properties()
934 }
935
936 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
937 self.inner.borrow().resolved_modifiers
938 }
939
940 pub fn total_offset(&self) -> Point {
941 self.resolved_modifiers().offset()
942 }
943
944 pub fn modifier_capabilities(&self) -> NodeCapabilities {
945 self.inner.borrow().modifier_capabilities
946 }
947
948 pub fn has_layout_modifier_nodes(&self) -> bool {
949 self.modifier_capabilities()
950 .contains(NodeCapabilities::LAYOUT)
951 }
952
953 pub fn has_draw_modifier_nodes(&self) -> bool {
954 self.modifier_capabilities()
955 .contains(NodeCapabilities::DRAW)
956 }
957
958 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
959 self.modifier_capabilities()
960 .contains(NodeCapabilities::POINTER_INPUT)
961 }
962
963 pub fn has_semantics_modifier_nodes(&self) -> bool {
964 self.modifier_capabilities()
965 .contains(NodeCapabilities::SEMANTICS)
966 }
967
968 pub fn has_focus_modifier_nodes(&self) -> bool {
969 self.modifier_capabilities()
970 .contains(NodeCapabilities::FOCUS)
971 }
972
973 pub fn set_debug_modifiers(&self, enabled: bool) {
974 self.inner.borrow_mut().set_debug_modifiers(enabled);
975 }
976
977 pub fn measure<'a>(
978 &self,
979 composer: &Composer,
980 node_id: NodeId,
981 constraints: Constraints,
982 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
983 error: &'a RefCell<Option<NodeError>>,
984 ) -> Result<MeasureResult, NodeError> {
985 let (policy, mut state, slots_host, placement_scratch) = {
986 let mut inner = self.inner.borrow_mut();
987 let policy = Rc::clone(&inner.measure_policy);
988 let state = std::mem::take(&mut inner.state);
989 let slots_host = Rc::clone(&inner.slots);
990 let placement_scratch = std::mem::take(&mut inner.placement_scratch);
991 (policy, state, slots_host, placement_scratch)
992 };
993 state.begin_pass();
994
995 let previous = composer.phase();
996 if !matches!(previous, Phase::Measure | Phase::Layout) {
997 composer.enter_phase(Phase::Measure);
998 }
999
1000 let constraints_copy = constraints;
1001 let ((result, placement_scratch), _) =
1010 composer.subcompose_slot(&slots_host, Some(node_id), |inner_composer| {
1011 let mut scope = SubcomposeMeasureScopeImpl::new(SubcomposeMeasureScopeInit {
1012 composer: inner_composer.clone(),
1013 state: &mut state,
1014 constraints: constraints_copy,
1015 measurer,
1016 error,
1017 parent_handle: self.clone(),
1018 root_id: node_id,
1019 placement_scratch,
1020 });
1021 let result = (policy)(&mut scope, constraints_copy);
1022 (result, scope.into_placement_scratch())
1023 })?;
1024
1025 state.finish_pass();
1026
1027 if previous != composer.phase() {
1028 composer.enter_phase(previous);
1029 }
1030
1031 {
1032 let mut inner = self.inner.borrow_mut();
1033 inner.state = state;
1034 inner.placement_scratch = placement_scratch;
1035
1036 inner.last_placements = result.placements.iter().map(|p| p.node_id).collect();
1041 }
1042
1043 Ok(result)
1044 }
1045
1046 pub(crate) fn recycle_placement_scratch(&self, mut placements: Vec<Placement>) {
1047 placements.clear();
1048 let mut inner = self.inner.borrow_mut();
1049 if placements.capacity() > inner.placement_scratch.capacity() {
1050 inner.placement_scratch = placements;
1051 }
1052 }
1053
1054 pub fn set_active_children<I>(&self, children: I)
1055 where
1056 I: IntoIterator<Item = NodeId>,
1057 {
1058 let mut inner = self.inner.borrow_mut();
1059 inner.children.clear();
1060 inner.children.extend(children);
1061 }
1062}
1063
1064fn current_subcompose_children(inner: &SubcomposeLayoutNodeInner) -> Vec<NodeId> {
1065 if !inner.last_placements.is_empty() {
1066 inner.last_placements.clone()
1067 } else {
1068 inner.children.clone()
1069 }
1070}
1071
1072struct SubcomposeLayoutNodeInner {
1073 modifier: Modifier,
1074 modifier_chain: ModifierChainHandle,
1075 resolved_modifiers: ResolvedModifiers,
1076 modifier_capabilities: NodeCapabilities,
1077 state: SubcomposeState,
1078 measure_policy: Rc<MeasurePolicy>,
1079 children: Vec<NodeId>,
1080 slots: Rc<SlotsHost>,
1081 debug_modifiers: bool,
1082 virtual_nodes: HashMap<NodeId, Rc<LayoutNode>>,
1084 last_placements: Vec<NodeId>,
1087 placement_scratch: Vec<Placement>,
1088 measured_children_scratch: Rc<RefCell<HashMap<NodeId, Rc<MeasuredNode>>>>,
1089}
1090
1091impl SubcomposeLayoutNodeInner {
1092 fn new(measure_policy: Rc<MeasurePolicy>) -> Self {
1093 Self {
1094 modifier: Modifier::empty(),
1095 modifier_chain: ModifierChainHandle::new(),
1096 resolved_modifiers: ResolvedModifiers::default(),
1097 modifier_capabilities: NodeCapabilities::default(),
1098 state: SubcomposeState::default(),
1099 measure_policy,
1100 children: Vec::new(),
1101 slots: Rc::new(SlotsHost::new(SlotTable::default())),
1102 debug_modifiers: false,
1103 virtual_nodes: HashMap::new(),
1104 last_placements: Vec::new(),
1105 placement_scratch: Vec::new(),
1106 measured_children_scratch: Rc::new(RefCell::new(HashMap::default())),
1107 }
1108 }
1109
1110 fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
1111 self.measure_policy = policy;
1112 if let Err(err) = self.slots.reset() {
1117 log::error!(
1118 "failed to reset root measurement slots after measure policy update: {err}"
1119 );
1120 }
1121 }
1122
1123 fn set_modifier_collect(&mut self, modifier: Modifier) -> (Vec<ModifierInvalidation>, bool) {
1126 let modifier_changed = !self.modifier.structural_eq(&modifier);
1127 self.modifier = modifier;
1128 self.modifier_chain.set_debug_logging(self.debug_modifiers);
1129 let modifier_local_invalidations = self.modifier_chain.update(&self.modifier);
1130 self.resolved_modifiers = self.modifier_chain.resolved_modifiers();
1131 self.modifier_capabilities = self.modifier_chain.capabilities();
1132
1133 let mut invalidations = self.modifier_chain.take_invalidations();
1135 invalidations.extend(modifier_local_invalidations);
1136
1137 (invalidations, modifier_changed)
1138 }
1139
1140 fn set_debug_modifiers(&mut self, enabled: bool) {
1141 self.debug_modifiers = enabled;
1142 self.modifier_chain.set_debug_logging(enabled);
1143 }
1144}
1145
1146#[cfg(test)]
1147#[path = "tests/subcompose_layout_tests.rs"]
1148mod tests;