1use std::cell::{Cell, Ref, RefCell, RefMut};
2use std::collections::HashMap;
3use std::rc::Rc;
4
5use cranpose_core::{
6 Composer, NodeError, NodeId, Phase, SlotBackend, SlotId, SlotsHost, SubcomposeState,
7};
8
9use crate::modifier::{
10 collect_modifier_slices_into, Modifier, ModifierChainHandle, ModifierNodeSlices, Point,
11 ResolvedModifiers, Size,
12};
13use crate::widgets::nodes::{
14 allocate_virtual_node_id, is_virtual_node, register_layout_node, LayoutNode, LayoutState,
15};
16
17use cranpose_foundation::{InvalidationKind, ModifierInvalidation, NodeCapabilities};
18
19pub use cranpose_ui_layout::{Constraints, MeasureResult, Placement};
20
21#[derive(Clone, Copy, Debug)]
26pub struct SubcomposeChild {
27 node_id: NodeId,
28 measured_size: Option<Size>,
31}
32
33impl SubcomposeChild {
34 pub fn new(node_id: NodeId) -> Self {
35 Self {
36 node_id,
37 measured_size: None,
38 }
39 }
40
41 pub fn with_size(node_id: NodeId, size: Size) -> Self {
43 Self {
44 node_id,
45 measured_size: Some(size),
46 }
47 }
48
49 pub fn node_id(&self) -> NodeId {
50 self.node_id
51 }
52
53 pub fn size(&self) -> Size {
58 self.measured_size.unwrap_or(Size {
59 width: 0.0,
60 height: 0.0,
61 })
62 }
63
64 pub fn width(&self) -> f32 {
66 self.size().width
67 }
68
69 pub fn height(&self) -> f32 {
71 self.size().height
72 }
73
74 pub fn set_size(&mut self, size: Size) {
76 self.measured_size = Some(size);
77 }
78}
79
80impl PartialEq for SubcomposeChild {
81 fn eq(&self, other: &Self) -> bool {
82 self.node_id == other.node_id
83 }
84}
85
86pub type SubcomposePlaceable = cranpose_ui_layout::Placeable;
92
93pub trait SubcomposeLayoutScope {
95 fn constraints(&self) -> Constraints;
96
97 fn layout<I>(&mut self, width: f32, height: f32, placements: I) -> MeasureResult
98 where
99 I: IntoIterator<Item = Placement>,
100 {
101 MeasureResult::new(Size { width, height }, placements.into_iter().collect())
102 }
103}
104
105pub trait SubcomposeMeasureScope: SubcomposeLayoutScope {
107 fn subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<SubcomposeChild>
108 where
109 Content: FnMut() + 'static;
110
111 fn measure(&mut self, child: SubcomposeChild, constraints: Constraints) -> SubcomposePlaceable;
113
114 fn node_has_no_parent(&self, node_id: NodeId) -> bool;
117}
118
119pub struct SubcomposeMeasureScopeImpl<'a> {
121 composer: Composer,
122 state: &'a mut SubcomposeState,
123 constraints: Constraints,
124 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
125 error: Rc<RefCell<Option<NodeError>>>,
126 parent_handle: SubcomposeLayoutNodeHandle,
127 root_id: NodeId,
128}
129
130impl<'a> SubcomposeMeasureScopeImpl<'a> {
131 pub fn new(
132 composer: Composer,
133 state: &'a mut SubcomposeState,
134 constraints: Constraints,
135 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
136 error: Rc<RefCell<Option<NodeError>>>,
137
138 parent_handle: SubcomposeLayoutNodeHandle,
139 root_id: NodeId,
140 ) -> Self {
141 Self {
142 composer,
143 state,
144 constraints,
145 measurer,
146 error,
147 parent_handle,
148 root_id,
149 }
150 }
151
152 fn record_error(&self, err: NodeError) {
153 let mut slot = self.error.borrow_mut();
154 if slot.is_none() {
155 eprintln!("[SubcomposeLayout] Error suppressed: {:?}", err);
156 *slot = Some(err);
157 }
158 }
159
160 fn perform_subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<NodeId>
161 where
162 Content: FnMut() + 'static,
163 {
164 let content_holder = self.state.callback_holder(slot_id);
165 content_holder.update(content);
166 let mut inner = self.parent_handle.inner.borrow_mut();
167
168 let (virtual_node_id, is_reused) =
170 if let Some(node_id) = self.state.take_node_from_reusables(slot_id) {
171 (node_id, true)
172 } else {
173 let id = allocate_virtual_node_id();
174 let node = LayoutNode::new_virtual();
175 if let Err(e) = self
179 .composer
180 .register_virtual_node(id, Box::new(node.clone()))
181 {
182 eprintln!(
183 "[Subcompose] Failed to register virtual node {}: {:?}",
184 id, e
185 );
186 }
187 register_layout_node(id, &node);
188
189 inner.virtual_nodes.insert(id, Rc::new(node));
190 inner.children.push(id);
191 (id, false)
192 };
193
194 if let Some(v_node) = inner.virtual_nodes.get(&virtual_node_id) {
196 v_node.set_parent(self.root_id);
197 }
198
199 drop(inner);
200
201 if is_reused {
205 self.composer.clear_node_children(virtual_node_id);
206 }
207
208 let slot_host = self.state.get_or_create_slots(slot_id);
209 let holder_for_slot = content_holder.clone();
210 let scopes = self
211 .composer
212 .subcompose_slot(&slot_host, Some(virtual_node_id), move |_| {
213 compose_subcompose_slot_content(holder_for_slot.clone());
214 })
215 .map(|(_, scopes)| scopes)
216 .unwrap_or_default();
217
218 self.state
219 .register_active(slot_id, &[virtual_node_id], &scopes);
220
221 self.composer.get_node_children(virtual_node_id)
225 }
226}
227
228impl<'a> SubcomposeLayoutScope for SubcomposeMeasureScopeImpl<'a> {
229 fn constraints(&self) -> Constraints {
230 self.constraints
231 }
232}
233
234impl<'a> SubcomposeMeasureScope for SubcomposeMeasureScopeImpl<'a> {
235 fn subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<SubcomposeChild>
236 where
237 Content: FnMut() + 'static,
238 {
239 let nodes = self.perform_subcompose(slot_id, content);
240 nodes.into_iter().map(SubcomposeChild::new).collect()
241 }
242
243 fn measure(&mut self, child: SubcomposeChild, constraints: Constraints) -> SubcomposePlaceable {
244 if self.error.borrow().is_some() {
245 return SubcomposePlaceable::value(0.0, 0.0, child.node_id);
247 }
248
249 if let Err(err) = self.composer.apply_pending_commands() {
250 self.record_error(err);
251 return SubcomposePlaceable::value(0.0, 0.0, child.node_id);
252 }
253
254 let size = (self.measurer)(child.node_id, constraints);
255 SubcomposePlaceable::value(size.width, size.height, child.node_id)
256 }
257
258 fn node_has_no_parent(&self, node_id: NodeId) -> bool {
259 self.composer.node_has_no_parent(node_id)
260 }
261}
262
263impl<'a> SubcomposeMeasureScopeImpl<'a> {
264 pub fn subcompose_with_size<Content, F>(
269 &mut self,
270 slot_id: SlotId,
271 content: Content,
272 estimate_size: F,
273 ) -> Vec<SubcomposeChild>
274 where
275 Content: FnMut() + 'static,
276 F: Fn(usize) -> Size,
277 {
278 let nodes = self.perform_subcompose(slot_id, content);
279 nodes
280 .into_iter()
281 .enumerate()
282 .map(|(i, node_id)| SubcomposeChild::with_size(node_id, estimate_size(i)))
283 .collect()
284 }
285
286 pub fn active_slots_count(&self) -> usize {
290 self.state.active_slots_count()
291 }
292
293 pub fn reusable_slots_count(&self) -> usize {
297 self.state.reusable_slots_count()
298 }
299
300 pub fn register_content_type(&mut self, slot_id: SlotId, content_type: u64) {
306 self.state.register_content_type(slot_id, content_type);
307 }
308
309 pub fn update_content_type(&mut self, slot_id: SlotId, content_type: Option<u64>) {
315 self.state.update_content_type(slot_id, content_type);
316 }
317
318 pub fn was_last_slot_reused(&self) -> Option<bool> {
326 self.state.was_last_slot_reused()
327 }
328}
329
330fn compose_subcompose_slot_content(holder: cranpose_core::CallbackHolder) {
331 cranpose_core::with_current_composer(|composer| {
332 let holder_for_recompose = holder.clone();
333 composer.set_recranpose_callback(move |_composer| {
334 let invoke = holder_for_recompose.clone_rc();
335 invoke();
336 });
337 });
338
339 let invoke = holder.clone_rc();
340 invoke();
341}
342
343pub type MeasurePolicy =
345 dyn for<'scope> Fn(&mut SubcomposeMeasureScopeImpl<'scope>, Constraints) -> MeasureResult;
346
347pub struct SubcomposeLayoutNode {
349 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
350 parent: Cell<Option<NodeId>>,
352 id: Cell<Option<NodeId>>,
354 needs_measure: Cell<bool>,
356 needs_layout: Cell<bool>,
357 needs_semantics: Cell<bool>,
358 needs_redraw: Cell<bool>,
359 needs_pointer_pass: Cell<bool>,
360 needs_focus_sync: Cell<bool>,
361 virtual_children_count: Cell<usize>,
362 layout_state: Rc<RefCell<LayoutState>>,
364 modifier_slices_buffer: RefCell<ModifierNodeSlices>,
366 modifier_slices_snapshot: RefCell<Rc<ModifierNodeSlices>>,
367}
368
369impl SubcomposeLayoutNode {
370 pub fn new(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
371 let inner = Rc::new(RefCell::new(SubcomposeLayoutNodeInner::new(measure_policy)));
372 let node = Self {
373 inner,
374 parent: Cell::new(None),
375 id: Cell::new(None),
376 needs_measure: Cell::new(true),
377 needs_layout: Cell::new(true),
378 needs_semantics: Cell::new(true),
379 needs_redraw: Cell::new(true),
380 needs_pointer_pass: Cell::new(false),
381 needs_focus_sync: Cell::new(false),
382 virtual_children_count: Cell::new(0),
383 layout_state: Rc::new(RefCell::new(LayoutState::default())),
384 modifier_slices_buffer: RefCell::new(ModifierNodeSlices::default()),
385 modifier_slices_snapshot: RefCell::new(Rc::default()),
386 };
387 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
390 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
391 node.update_modifier_slices_cache();
392 node
393 }
394
395 pub fn with_content_type_policy(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
401 let mut inner_data = SubcomposeLayoutNodeInner::new(measure_policy);
402 inner_data
403 .state
404 .set_policy(Box::new(cranpose_core::ContentTypeReusePolicy::new()));
405 let inner = Rc::new(RefCell::new(inner_data));
406 let node = Self {
407 inner,
408 parent: Cell::new(None),
409 id: Cell::new(None),
410 needs_measure: Cell::new(true),
411 needs_layout: Cell::new(true),
412 needs_semantics: Cell::new(true),
413 needs_redraw: Cell::new(true),
414 needs_pointer_pass: Cell::new(false),
415 needs_focus_sync: Cell::new(false),
416 virtual_children_count: Cell::new(0),
417 layout_state: Rc::new(RefCell::new(LayoutState::default())),
418 modifier_slices_buffer: RefCell::new(ModifierNodeSlices::default()),
419 modifier_slices_snapshot: RefCell::new(Rc::default()),
420 };
421 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
424 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
425 node.update_modifier_slices_cache();
426 node
427 }
428
429 pub fn handle(&self) -> SubcomposeLayoutNodeHandle {
430 SubcomposeLayoutNodeHandle {
431 inner: Rc::clone(&self.inner),
432 }
433 }
434
435 pub fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
436 let mut inner = self.inner.borrow_mut();
437 inner.set_measure_policy(policy);
438 inner.state.invalidate_scopes();
439 drop(inner);
440 self.mark_needs_measure();
441 if let Some(id) = self.id.get() {
442 cranpose_core::bubble_measure_dirty_in_composer(id);
443 }
444 }
445
446 pub fn set_modifier(&mut self, modifier: Modifier) {
447 let prev_caps = self.modifier_capabilities();
449 let (invalidations, modifier_changed) = {
451 let mut inner = self.inner.borrow_mut();
452 inner.set_modifier_collect(modifier)
453 };
454 self.dispatch_modifier_invalidations(&invalidations, prev_caps);
457 if modifier_changed {
458 self.update_modifier_slices_cache();
459 self.mark_needs_measure();
460 self.request_semantics_update();
461 }
462 }
463
464 fn update_modifier_slices_cache(&self) {
466 let inner = self.inner.borrow();
467 let mut buffer = self.modifier_slices_buffer.borrow_mut();
468 collect_modifier_slices_into(inner.modifier_chain.chain(), &mut buffer);
469 *self.modifier_slices_snapshot.borrow_mut() = Rc::new(buffer.clone());
470 }
471
472 pub fn set_debug_modifiers(&mut self, enabled: bool) {
473 self.inner.borrow_mut().set_debug_modifiers(enabled);
474 }
475
476 pub fn modifier(&self) -> Modifier {
477 self.handle().modifier()
478 }
479
480 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
481 self.inner.borrow().resolved_modifiers
482 }
483
484 pub fn layout_state(&self) -> LayoutState {
486 self.layout_state.borrow().clone()
487 }
488
489 pub fn set_position(&self, position: Point) {
491 let mut state = self.layout_state.borrow_mut();
492 state.position = position;
493 state.is_placed = true;
494 }
495
496 pub fn set_measured_size(&self, size: Size) {
498 let mut state = self.layout_state.borrow_mut();
499 state.size = size;
500 }
501
502 pub fn clear_placed(&self) {
504 self.layout_state.borrow_mut().is_placed = false;
505 }
506
507 pub fn modifier_slices_snapshot(&self) -> Rc<ModifierNodeSlices> {
509 self.update_modifier_slices_cache();
510 self.modifier_slices_snapshot.borrow().clone()
511 }
512
513 pub fn state(&self) -> Ref<'_, SubcomposeState> {
514 Ref::map(self.inner.borrow(), |inner| &inner.state)
515 }
516
517 pub fn state_mut(&self) -> RefMut<'_, SubcomposeState> {
518 RefMut::map(self.inner.borrow_mut(), |inner| &mut inner.state)
519 }
520
521 pub fn active_children(&self) -> Vec<NodeId> {
522 self.inner.borrow().children.clone()
523 }
524
525 pub fn mark_needs_measure(&self) {
527 self.needs_measure.set(true);
528 self.needs_layout.set(true);
529 }
530
531 pub fn mark_needs_layout_flag(&self) {
533 self.needs_layout.set(true);
534 }
535
536 pub fn mark_needs_redraw(&self) {
538 self.needs_redraw.set(true);
539 if let Some(id) = self.id.get() {
540 crate::schedule_draw_repass(id);
541 }
542 crate::request_render_invalidation();
543 }
544
545 pub fn needs_measure(&self) -> bool {
547 self.needs_measure.get()
548 }
549
550 pub fn mark_needs_semantics(&self) {
552 self.needs_semantics.set(true);
553 }
554
555 pub fn needs_semantics_flag(&self) -> bool {
557 self.needs_semantics.get()
558 }
559
560 pub fn needs_redraw(&self) -> bool {
562 self.needs_redraw.get()
563 }
564
565 pub fn clear_needs_redraw(&self) {
566 self.needs_redraw.set(false);
567 }
568
569 pub fn mark_needs_pointer_pass(&self) {
571 self.needs_pointer_pass.set(true);
572 }
573
574 pub fn needs_pointer_pass(&self) -> bool {
576 self.needs_pointer_pass.get()
577 }
578
579 pub fn clear_needs_pointer_pass(&self) {
581 self.needs_pointer_pass.set(false);
582 }
583
584 pub fn mark_needs_focus_sync(&self) {
586 self.needs_focus_sync.set(true);
587 }
588
589 pub fn needs_focus_sync(&self) -> bool {
591 self.needs_focus_sync.get()
592 }
593
594 pub fn clear_needs_focus_sync(&self) {
596 self.needs_focus_sync.set(false);
597 }
598
599 fn request_semantics_update(&self) {
600 let already_dirty = self.needs_semantics.replace(true);
601 if already_dirty {
602 return;
603 }
604
605 if let Some(id) = self.id.get() {
606 cranpose_core::queue_semantics_invalidation(id);
607 }
608 }
609
610 pub fn modifier_capabilities(&self) -> NodeCapabilities {
612 self.inner.borrow().modifier_capabilities
613 }
614
615 pub fn has_layout_modifier_nodes(&self) -> bool {
616 self.modifier_capabilities()
617 .contains(NodeCapabilities::LAYOUT)
618 }
619
620 pub fn has_draw_modifier_nodes(&self) -> bool {
621 self.modifier_capabilities()
622 .contains(NodeCapabilities::DRAW)
623 }
624
625 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
626 self.modifier_capabilities()
627 .contains(NodeCapabilities::POINTER_INPUT)
628 }
629
630 pub fn has_semantics_modifier_nodes(&self) -> bool {
631 self.modifier_capabilities()
632 .contains(NodeCapabilities::SEMANTICS)
633 }
634
635 pub fn has_focus_modifier_nodes(&self) -> bool {
636 self.modifier_capabilities()
637 .contains(NodeCapabilities::FOCUS)
638 }
639
640 fn dispatch_modifier_invalidations(
647 &self,
648 invalidations: &[ModifierInvalidation],
649 prev_caps: NodeCapabilities,
650 ) {
651 let curr_caps = self.modifier_capabilities();
652 for invalidation in invalidations {
653 match invalidation.kind() {
654 InvalidationKind::Layout => {
655 if curr_caps.contains(NodeCapabilities::LAYOUT)
656 || prev_caps.contains(NodeCapabilities::LAYOUT)
657 {
658 self.mark_needs_measure();
659 }
660 }
661 InvalidationKind::Draw => {
662 if curr_caps.contains(NodeCapabilities::DRAW)
663 || prev_caps.contains(NodeCapabilities::DRAW)
664 {
665 self.mark_needs_redraw();
666 }
667 }
668 InvalidationKind::PointerInput => {
669 if curr_caps.contains(NodeCapabilities::POINTER_INPUT)
670 || prev_caps.contains(NodeCapabilities::POINTER_INPUT)
671 {
672 self.mark_needs_pointer_pass();
673 crate::request_pointer_invalidation();
674 if let Some(id) = self.id.get() {
676 crate::schedule_pointer_repass(id);
677 }
678 }
679 }
680 InvalidationKind::Semantics => {
681 self.request_semantics_update();
682 }
683 InvalidationKind::Focus => {
684 if curr_caps.contains(NodeCapabilities::FOCUS)
685 || prev_caps.contains(NodeCapabilities::FOCUS)
686 {
687 self.mark_needs_focus_sync();
688 crate::request_focus_invalidation();
689 if let Some(id) = self.id.get() {
691 crate::schedule_focus_invalidation(id);
692 }
693 }
694 }
695 }
696 }
697 }
698}
699
700impl cranpose_core::Node for SubcomposeLayoutNode {
701 fn mount(&mut self) {
702 let mut inner = self.inner.borrow_mut();
703 let (chain, mut context) = inner.modifier_chain.chain_and_context_mut();
704 chain.repair_chain();
705 chain.attach_nodes(&mut *context);
706 }
707
708 fn unmount(&mut self) {
709 self.inner
710 .borrow_mut()
711 .modifier_chain
712 .chain_mut()
713 .detach_nodes();
714 }
715
716 fn insert_child(&mut self, child: NodeId) {
717 let mut inner = self.inner.borrow_mut();
718 if inner.children.contains(&child) {
719 return;
720 }
721 if is_virtual_node(child) {
722 let count = self.virtual_children_count.get();
723 self.virtual_children_count.set(count + 1);
724 }
725 inner.children.push(child);
726 }
727
728 fn remove_child(&mut self, child: NodeId) {
729 let mut inner = self.inner.borrow_mut();
730 let before = inner.children.len();
731 inner.children.retain(|&id| id != child);
732 if inner.children.len() < before && is_virtual_node(child) {
733 let count = self.virtual_children_count.get();
734 if count > 0 {
735 self.virtual_children_count.set(count - 1);
736 }
737 }
738 }
739
740 fn move_child(&mut self, from: usize, to: usize) {
741 let mut inner = self.inner.borrow_mut();
742 if from == to || from >= inner.children.len() {
743 return;
744 }
745 let child = inner.children.remove(from);
746 let target = to.min(inner.children.len());
747 inner.children.insert(target, child);
748 }
749
750 fn update_children(&mut self, children: &[NodeId]) {
751 let mut inner = self.inner.borrow_mut();
752 inner.children.clear();
753 inner.children.extend_from_slice(children);
754 }
755
756 fn children(&self) -> Vec<NodeId> {
757 let inner = self.inner.borrow();
758 if !inner.last_placements.is_empty() {
759 inner.last_placements.clone()
760 } else {
761 inner.children.clone()
762 }
763 }
764
765 fn set_node_id(&mut self, id: NodeId) {
766 self.id.set(Some(id));
767 self.inner.borrow_mut().modifier_chain.set_node_id(Some(id));
768 }
769
770 fn on_attached_to_parent(&mut self, parent: NodeId) {
771 self.parent.set(Some(parent));
772 }
773
774 fn on_removed_from_parent(&mut self) {
775 self.parent.set(None);
776 }
777
778 fn parent(&self) -> Option<NodeId> {
779 self.parent.get()
780 }
781
782 fn mark_needs_layout(&self) {
783 self.needs_layout.set(true);
784 }
785
786 fn needs_layout(&self) -> bool {
787 self.needs_layout.get()
788 }
789
790 fn mark_needs_measure(&self) {
791 self.needs_measure.set(true);
792 self.needs_layout.set(true); }
794
795 fn needs_measure(&self) -> bool {
796 self.needs_measure.get()
797 }
798
799 fn mark_needs_semantics(&self) {
800 self.needs_semantics.set(true);
801 }
802
803 fn needs_semantics(&self) -> bool {
804 self.needs_semantics.get()
805 }
806
807 fn set_parent_for_bubbling(&mut self, parent: NodeId) {
809 self.parent.set(Some(parent));
810 }
811}
812
813#[derive(Clone)]
814pub struct SubcomposeLayoutNodeHandle {
815 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
816}
817
818impl SubcomposeLayoutNodeHandle {
819 pub fn modifier(&self) -> Modifier {
820 self.inner.borrow().modifier.clone()
821 }
822
823 pub fn layout_properties(&self) -> crate::modifier::LayoutProperties {
824 self.resolved_modifiers().layout_properties()
825 }
826
827 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
828 self.inner.borrow().resolved_modifiers
829 }
830
831 pub fn total_offset(&self) -> Point {
832 self.resolved_modifiers().offset()
833 }
834
835 pub fn modifier_capabilities(&self) -> NodeCapabilities {
836 self.inner.borrow().modifier_capabilities
837 }
838
839 pub fn has_layout_modifier_nodes(&self) -> bool {
840 self.modifier_capabilities()
841 .contains(NodeCapabilities::LAYOUT)
842 }
843
844 pub fn has_draw_modifier_nodes(&self) -> bool {
845 self.modifier_capabilities()
846 .contains(NodeCapabilities::DRAW)
847 }
848
849 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
850 self.modifier_capabilities()
851 .contains(NodeCapabilities::POINTER_INPUT)
852 }
853
854 pub fn has_semantics_modifier_nodes(&self) -> bool {
855 self.modifier_capabilities()
856 .contains(NodeCapabilities::SEMANTICS)
857 }
858
859 pub fn has_focus_modifier_nodes(&self) -> bool {
860 self.modifier_capabilities()
861 .contains(NodeCapabilities::FOCUS)
862 }
863
864 pub fn set_debug_modifiers(&self, enabled: bool) {
865 self.inner.borrow_mut().set_debug_modifiers(enabled);
866 }
867
868 pub fn measure<'a>(
869 &self,
870 composer: &Composer,
871 node_id: NodeId,
872 constraints: Constraints,
873 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
874 error: Rc<RefCell<Option<NodeError>>>,
875 ) -> Result<MeasureResult, NodeError> {
876 let (policy, mut state, slots) = {
877 let mut inner = self.inner.borrow_mut();
878 let policy = Rc::clone(&inner.measure_policy);
879 let state = std::mem::take(&mut inner.state);
880 let slots = std::mem::take(&mut inner.slots);
881 (policy, state, slots)
882 };
883 state.begin_pass();
884
885 let previous = composer.phase();
886 if !matches!(previous, Phase::Measure | Phase::Layout) {
887 composer.enter_phase(Phase::Measure);
888 }
889
890 let slots_host = Rc::new(SlotsHost::new(slots));
891 let constraints_copy = constraints;
892 let (result, _) =
901 composer.subcompose_slot(&slots_host, Some(node_id), |inner_composer| {
902 let mut scope = SubcomposeMeasureScopeImpl::new(
903 inner_composer.clone(),
904 &mut state,
905 constraints_copy,
906 measurer,
907 Rc::clone(&error),
908 self.clone(), node_id, );
911 (policy)(&mut scope, constraints_copy)
912 })?;
913
914 state.finish_pass();
915
916 if previous != composer.phase() {
917 composer.enter_phase(previous);
918 }
919
920 {
921 let mut inner = self.inner.borrow_mut();
922 inner.slots = slots_host.take();
923 inner.state = state;
924
925 inner.last_placements = result.placements.iter().map(|p| p.node_id).collect();
930 }
931
932 Ok(result)
933 }
934
935 pub fn set_active_children<I>(&self, children: I)
936 where
937 I: IntoIterator<Item = NodeId>,
938 {
939 let mut inner = self.inner.borrow_mut();
940 inner.children.clear();
941 inner.children.extend(children);
942 }
943}
944
945struct SubcomposeLayoutNodeInner {
946 modifier: Modifier,
947 modifier_chain: ModifierChainHandle,
948 resolved_modifiers: ResolvedModifiers,
949 modifier_capabilities: NodeCapabilities,
950 state: SubcomposeState,
951 measure_policy: Rc<MeasurePolicy>,
952 children: Vec<NodeId>,
953 slots: SlotBackend,
954 debug_modifiers: bool,
955 virtual_nodes: HashMap<NodeId, Rc<LayoutNode>>,
957 last_placements: Vec<NodeId>,
960}
961
962impl SubcomposeLayoutNodeInner {
963 fn new(measure_policy: Rc<MeasurePolicy>) -> Self {
964 Self {
965 modifier: Modifier::empty(),
966 modifier_chain: ModifierChainHandle::new(),
967 resolved_modifiers: ResolvedModifiers::default(),
968 modifier_capabilities: NodeCapabilities::default(),
969 state: SubcomposeState::default(),
970 measure_policy,
971 children: Vec::new(),
972 slots: SlotBackend::default(),
973 debug_modifiers: false,
974 virtual_nodes: HashMap::new(),
975 last_placements: Vec::new(),
976 }
977 }
978
979 fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
980 self.measure_policy = policy;
981 self.slots = SlotBackend::default();
986 }
987
988 fn set_modifier_collect(&mut self, modifier: Modifier) -> (Vec<ModifierInvalidation>, bool) {
991 let modifier_changed = !self.modifier.structural_eq(&modifier);
992 self.modifier = modifier;
993 self.modifier_chain.set_debug_logging(self.debug_modifiers);
994 let modifier_local_invalidations = self.modifier_chain.update(&self.modifier);
995 self.resolved_modifiers = self.modifier_chain.resolved_modifiers();
996 self.modifier_capabilities = self.modifier_chain.capabilities();
997
998 let mut invalidations = self.modifier_chain.take_invalidations();
1000 invalidations.extend(modifier_local_invalidations);
1001
1002 (invalidations, modifier_changed)
1003 }
1004
1005 fn set_debug_modifiers(&mut self, enabled: bool) {
1006 self.debug_modifiers = enabled;
1007 self.modifier_chain.set_debug_logging(enabled);
1008 }
1009}
1010
1011#[cfg(test)]
1012#[path = "tests/subcompose_layout_tests.rs"]
1013mod tests;