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.modifier_slices_snapshot.borrow().clone()
510 }
511
512 pub fn state(&self) -> Ref<'_, SubcomposeState> {
513 Ref::map(self.inner.borrow(), |inner| &inner.state)
514 }
515
516 pub fn state_mut(&self) -> RefMut<'_, SubcomposeState> {
517 RefMut::map(self.inner.borrow_mut(), |inner| &mut inner.state)
518 }
519
520 pub fn active_children(&self) -> Vec<NodeId> {
521 self.inner.borrow().children.clone()
522 }
523
524 pub fn mark_needs_measure(&self) {
526 self.needs_measure.set(true);
527 self.needs_layout.set(true);
528 }
529
530 pub fn mark_needs_layout_flag(&self) {
532 self.needs_layout.set(true);
533 }
534
535 pub fn mark_needs_redraw(&self) {
537 self.needs_redraw.set(true);
538 if let Some(id) = self.id.get() {
539 crate::schedule_draw_repass(id);
540 }
541 crate::request_render_invalidation();
542 }
543
544 pub fn needs_measure(&self) -> bool {
546 self.needs_measure.get()
547 }
548
549 pub fn mark_needs_semantics(&self) {
551 self.needs_semantics.set(true);
552 }
553
554 pub fn needs_semantics_flag(&self) -> bool {
556 self.needs_semantics.get()
557 }
558
559 pub fn needs_redraw(&self) -> bool {
561 self.needs_redraw.get()
562 }
563
564 pub fn clear_needs_redraw(&self) {
565 self.needs_redraw.set(false);
566 }
567
568 pub fn mark_needs_pointer_pass(&self) {
570 self.needs_pointer_pass.set(true);
571 }
572
573 pub fn needs_pointer_pass(&self) -> bool {
575 self.needs_pointer_pass.get()
576 }
577
578 pub fn clear_needs_pointer_pass(&self) {
580 self.needs_pointer_pass.set(false);
581 }
582
583 pub fn mark_needs_focus_sync(&self) {
585 self.needs_focus_sync.set(true);
586 }
587
588 pub fn needs_focus_sync(&self) -> bool {
590 self.needs_focus_sync.get()
591 }
592
593 pub fn clear_needs_focus_sync(&self) {
595 self.needs_focus_sync.set(false);
596 }
597
598 fn request_semantics_update(&self) {
599 let already_dirty = self.needs_semantics.replace(true);
600 if already_dirty {
601 return;
602 }
603
604 if let Some(id) = self.id.get() {
605 cranpose_core::queue_semantics_invalidation(id);
606 }
607 }
608
609 pub fn modifier_capabilities(&self) -> NodeCapabilities {
611 self.inner.borrow().modifier_capabilities
612 }
613
614 pub fn has_layout_modifier_nodes(&self) -> bool {
615 self.modifier_capabilities()
616 .contains(NodeCapabilities::LAYOUT)
617 }
618
619 pub fn has_draw_modifier_nodes(&self) -> bool {
620 self.modifier_capabilities()
621 .contains(NodeCapabilities::DRAW)
622 }
623
624 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
625 self.modifier_capabilities()
626 .contains(NodeCapabilities::POINTER_INPUT)
627 }
628
629 pub fn has_semantics_modifier_nodes(&self) -> bool {
630 self.modifier_capabilities()
631 .contains(NodeCapabilities::SEMANTICS)
632 }
633
634 pub fn has_focus_modifier_nodes(&self) -> bool {
635 self.modifier_capabilities()
636 .contains(NodeCapabilities::FOCUS)
637 }
638
639 fn dispatch_modifier_invalidations(
646 &self,
647 invalidations: &[ModifierInvalidation],
648 prev_caps: NodeCapabilities,
649 ) {
650 let curr_caps = self.modifier_capabilities();
651 for invalidation in invalidations {
652 match invalidation.kind() {
653 InvalidationKind::Layout => {
654 if curr_caps.contains(NodeCapabilities::LAYOUT)
655 || prev_caps.contains(NodeCapabilities::LAYOUT)
656 {
657 self.mark_needs_measure();
658 }
659 }
660 InvalidationKind::Draw => {
661 if curr_caps.contains(NodeCapabilities::DRAW)
662 || prev_caps.contains(NodeCapabilities::DRAW)
663 {
664 self.mark_needs_redraw();
665 }
666 }
667 InvalidationKind::PointerInput => {
668 if curr_caps.contains(NodeCapabilities::POINTER_INPUT)
669 || prev_caps.contains(NodeCapabilities::POINTER_INPUT)
670 {
671 self.mark_needs_pointer_pass();
672 crate::request_pointer_invalidation();
673 if let Some(id) = self.id.get() {
675 crate::schedule_pointer_repass(id);
676 }
677 }
678 }
679 InvalidationKind::Semantics => {
680 self.request_semantics_update();
681 }
682 InvalidationKind::Focus => {
683 if curr_caps.contains(NodeCapabilities::FOCUS)
684 || prev_caps.contains(NodeCapabilities::FOCUS)
685 {
686 self.mark_needs_focus_sync();
687 crate::request_focus_invalidation();
688 if let Some(id) = self.id.get() {
690 crate::schedule_focus_invalidation(id);
691 }
692 }
693 }
694 }
695 }
696 }
697}
698
699impl cranpose_core::Node for SubcomposeLayoutNode {
700 fn mount(&mut self) {
701 let mut inner = self.inner.borrow_mut();
702 let (chain, mut context) = inner.modifier_chain.chain_and_context_mut();
703 chain.repair_chain();
704 chain.attach_nodes(&mut *context);
705 }
706
707 fn unmount(&mut self) {
708 self.inner
709 .borrow_mut()
710 .modifier_chain
711 .chain_mut()
712 .detach_nodes();
713 }
714
715 fn insert_child(&mut self, child: NodeId) {
716 let mut inner = self.inner.borrow_mut();
717 if inner.children.contains(&child) {
718 return;
719 }
720 if is_virtual_node(child) {
721 let count = self.virtual_children_count.get();
722 self.virtual_children_count.set(count + 1);
723 }
724 inner.children.push(child);
725 }
726
727 fn remove_child(&mut self, child: NodeId) {
728 let mut inner = self.inner.borrow_mut();
729 let before = inner.children.len();
730 inner.children.retain(|&id| id != child);
731 if inner.children.len() < before && is_virtual_node(child) {
732 let count = self.virtual_children_count.get();
733 if count > 0 {
734 self.virtual_children_count.set(count - 1);
735 }
736 }
737 }
738
739 fn move_child(&mut self, from: usize, to: usize) {
740 let mut inner = self.inner.borrow_mut();
741 if from == to || from >= inner.children.len() {
742 return;
743 }
744 let child = inner.children.remove(from);
745 let target = to.min(inner.children.len());
746 inner.children.insert(target, child);
747 }
748
749 fn update_children(&mut self, children: &[NodeId]) {
750 let mut inner = self.inner.borrow_mut();
751 inner.children.clear();
752 inner.children.extend_from_slice(children);
753 }
754
755 fn children(&self) -> Vec<NodeId> {
756 let inner = self.inner.borrow();
757 if !inner.last_placements.is_empty() {
758 inner.last_placements.clone()
759 } else {
760 inner.children.clone()
761 }
762 }
763
764 fn set_node_id(&mut self, id: NodeId) {
765 self.id.set(Some(id));
766 self.inner.borrow_mut().modifier_chain.set_node_id(Some(id));
767 }
768
769 fn on_attached_to_parent(&mut self, parent: NodeId) {
770 self.parent.set(Some(parent));
771 }
772
773 fn on_removed_from_parent(&mut self) {
774 self.parent.set(None);
775 }
776
777 fn parent(&self) -> Option<NodeId> {
778 self.parent.get()
779 }
780
781 fn mark_needs_layout(&self) {
782 self.needs_layout.set(true);
783 }
784
785 fn needs_layout(&self) -> bool {
786 self.needs_layout.get()
787 }
788
789 fn mark_needs_measure(&self) {
790 self.needs_measure.set(true);
791 self.needs_layout.set(true); }
793
794 fn needs_measure(&self) -> bool {
795 self.needs_measure.get()
796 }
797
798 fn mark_needs_semantics(&self) {
799 self.needs_semantics.set(true);
800 }
801
802 fn needs_semantics(&self) -> bool {
803 self.needs_semantics.get()
804 }
805
806 fn set_parent_for_bubbling(&mut self, parent: NodeId) {
808 self.parent.set(Some(parent));
809 }
810}
811
812#[derive(Clone)]
813pub struct SubcomposeLayoutNodeHandle {
814 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
815}
816
817impl SubcomposeLayoutNodeHandle {
818 pub fn modifier(&self) -> Modifier {
819 self.inner.borrow().modifier.clone()
820 }
821
822 pub fn layout_properties(&self) -> crate::modifier::LayoutProperties {
823 self.resolved_modifiers().layout_properties()
824 }
825
826 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
827 self.inner.borrow().resolved_modifiers
828 }
829
830 pub fn total_offset(&self) -> Point {
831 self.resolved_modifiers().offset()
832 }
833
834 pub fn modifier_capabilities(&self) -> NodeCapabilities {
835 self.inner.borrow().modifier_capabilities
836 }
837
838 pub fn has_layout_modifier_nodes(&self) -> bool {
839 self.modifier_capabilities()
840 .contains(NodeCapabilities::LAYOUT)
841 }
842
843 pub fn has_draw_modifier_nodes(&self) -> bool {
844 self.modifier_capabilities()
845 .contains(NodeCapabilities::DRAW)
846 }
847
848 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
849 self.modifier_capabilities()
850 .contains(NodeCapabilities::POINTER_INPUT)
851 }
852
853 pub fn has_semantics_modifier_nodes(&self) -> bool {
854 self.modifier_capabilities()
855 .contains(NodeCapabilities::SEMANTICS)
856 }
857
858 pub fn has_focus_modifier_nodes(&self) -> bool {
859 self.modifier_capabilities()
860 .contains(NodeCapabilities::FOCUS)
861 }
862
863 pub fn set_debug_modifiers(&self, enabled: bool) {
864 self.inner.borrow_mut().set_debug_modifiers(enabled);
865 }
866
867 pub fn measure<'a>(
868 &self,
869 composer: &Composer,
870 node_id: NodeId,
871 constraints: Constraints,
872 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
873 error: Rc<RefCell<Option<NodeError>>>,
874 ) -> Result<MeasureResult, NodeError> {
875 let (policy, mut state, slots) = {
876 let mut inner = self.inner.borrow_mut();
877 let policy = Rc::clone(&inner.measure_policy);
878 let state = std::mem::take(&mut inner.state);
879 let slots = std::mem::take(&mut inner.slots);
880 (policy, state, slots)
881 };
882 state.begin_pass();
883
884 let previous = composer.phase();
885 if !matches!(previous, Phase::Measure | Phase::Layout) {
886 composer.enter_phase(Phase::Measure);
887 }
888
889 let slots_host = Rc::new(SlotsHost::new(slots));
890 let constraints_copy = constraints;
891 let (result, _) =
900 composer.subcompose_slot(&slots_host, Some(node_id), |inner_composer| {
901 let mut scope = SubcomposeMeasureScopeImpl::new(
902 inner_composer.clone(),
903 &mut state,
904 constraints_copy,
905 measurer,
906 Rc::clone(&error),
907 self.clone(), node_id, );
910 (policy)(&mut scope, constraints_copy)
911 })?;
912
913 state.finish_pass();
914
915 if previous != composer.phase() {
916 composer.enter_phase(previous);
917 }
918
919 {
920 let mut inner = self.inner.borrow_mut();
921 inner.slots = slots_host.take();
922 inner.state = state;
923
924 inner.last_placements = result.placements.iter().map(|p| p.node_id).collect();
929 }
930
931 Ok(result)
932 }
933
934 pub fn set_active_children<I>(&self, children: I)
935 where
936 I: IntoIterator<Item = NodeId>,
937 {
938 let mut inner = self.inner.borrow_mut();
939 inner.children.clear();
940 inner.children.extend(children);
941 }
942}
943
944struct SubcomposeLayoutNodeInner {
945 modifier: Modifier,
946 modifier_chain: ModifierChainHandle,
947 resolved_modifiers: ResolvedModifiers,
948 modifier_capabilities: NodeCapabilities,
949 state: SubcomposeState,
950 measure_policy: Rc<MeasurePolicy>,
951 children: Vec<NodeId>,
952 slots: SlotBackend,
953 debug_modifiers: bool,
954 virtual_nodes: HashMap<NodeId, Rc<LayoutNode>>,
956 last_placements: Vec<NodeId>,
959}
960
961impl SubcomposeLayoutNodeInner {
962 fn new(measure_policy: Rc<MeasurePolicy>) -> Self {
963 Self {
964 modifier: Modifier::empty(),
965 modifier_chain: ModifierChainHandle::new(),
966 resolved_modifiers: ResolvedModifiers::default(),
967 modifier_capabilities: NodeCapabilities::default(),
968 state: SubcomposeState::default(),
969 measure_policy,
970 children: Vec::new(),
971 slots: SlotBackend::default(),
972 debug_modifiers: false,
973 virtual_nodes: HashMap::new(),
974 last_placements: Vec::new(),
975 }
976 }
977
978 fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
979 self.measure_policy = policy;
980 self.slots = SlotBackend::default();
985 }
986
987 fn set_modifier_collect(&mut self, modifier: Modifier) -> (Vec<ModifierInvalidation>, bool) {
990 let modifier_changed = !self.modifier.structural_eq(&modifier);
991 self.modifier = modifier;
992 self.modifier_chain.set_debug_logging(self.debug_modifiers);
993 let modifier_local_invalidations = self.modifier_chain.update(&self.modifier);
994 self.resolved_modifiers = self.modifier_chain.resolved_modifiers();
995 self.modifier_capabilities = self.modifier_chain.capabilities();
996
997 let mut invalidations = self.modifier_chain.take_invalidations();
999 invalidations.extend(modifier_local_invalidations);
1000
1001 (invalidations, modifier_changed)
1002 }
1003
1004 fn set_debug_modifiers(&mut self, enabled: bool) {
1005 self.debug_modifiers = enabled;
1006 self.modifier_chain.set_debug_logging(enabled);
1007 }
1008}
1009
1010#[cfg(test)]
1011#[path = "tests/subcompose_layout_tests.rs"]
1012mod tests;