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::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: &'a 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: &'a 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 self.composer.record_subcompose_child(virtual_node_id);
197
198 if let Some(v_node) = inner.virtual_nodes.get(&virtual_node_id) {
201 v_node.set_parent(self.root_id);
202 }
203
204 drop(inner);
205
206 let _ = self
207 .composer
208 .with_node_mut::<LayoutNode, _>(virtual_node_id, |node| {
209 node.set_parent(self.root_id);
210 });
211
212 if is_reused {
216 self.composer.clear_node_children(virtual_node_id);
217 }
218
219 let slot_host = self.state.get_or_create_slots(slot_id);
220 let holder_for_slot = content_holder.clone();
221 let scopes = self
222 .composer
223 .subcompose_slot(&slot_host, Some(virtual_node_id), move |_| {
224 compose_subcompose_slot_content(holder_for_slot.clone());
225 })
226 .map(|(_, scopes)| scopes)
227 .unwrap_or_default();
228
229 self.state
230 .register_active(slot_id, &[virtual_node_id], &scopes);
231
232 self.composer.get_node_children(virtual_node_id).to_vec()
236 }
237}
238
239impl<'a> SubcomposeLayoutScope for SubcomposeMeasureScopeImpl<'a> {
240 fn constraints(&self) -> Constraints {
241 self.constraints
242 }
243}
244
245impl<'a> SubcomposeMeasureScope for SubcomposeMeasureScopeImpl<'a> {
246 fn subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<SubcomposeChild>
247 where
248 Content: FnMut() + 'static,
249 {
250 let nodes = self.perform_subcompose(slot_id, content);
251 nodes.into_iter().map(SubcomposeChild::new).collect()
252 }
253
254 fn measure(&mut self, child: SubcomposeChild, constraints: Constraints) -> SubcomposePlaceable {
255 if self.error.borrow().is_some() {
256 return SubcomposePlaceable::value(0.0, 0.0, child.node_id);
258 }
259
260 if let Err(err) = self.composer.apply_pending_commands() {
261 self.record_error(err);
262 return SubcomposePlaceable::value(0.0, 0.0, child.node_id);
263 }
264
265 let size = (self.measurer)(child.node_id, constraints);
266 SubcomposePlaceable::value(size.width, size.height, child.node_id)
267 }
268
269 fn node_has_no_parent(&self, node_id: NodeId) -> bool {
270 self.composer.node_has_no_parent(node_id)
271 }
272}
273
274impl<'a> SubcomposeMeasureScopeImpl<'a> {
275 pub fn subcompose_with_size<Content, F>(
280 &mut self,
281 slot_id: SlotId,
282 content: Content,
283 estimate_size: F,
284 ) -> Vec<SubcomposeChild>
285 where
286 Content: FnMut() + 'static,
287 F: Fn(usize) -> Size,
288 {
289 let nodes = self.perform_subcompose(slot_id, content);
290 nodes
291 .into_iter()
292 .enumerate()
293 .map(|(i, node_id)| SubcomposeChild::with_size(node_id, estimate_size(i)))
294 .collect()
295 }
296
297 pub fn active_slots_count(&self) -> usize {
301 self.state.active_slots_count()
302 }
303
304 pub fn reusable_slots_count(&self) -> usize {
308 self.state.reusable_slots_count()
309 }
310
311 pub fn register_content_type(&mut self, slot_id: SlotId, content_type: u64) {
317 self.state.register_content_type(slot_id, content_type);
318 }
319
320 pub fn update_content_type(&mut self, slot_id: SlotId, content_type: Option<u64>) {
326 self.state.update_content_type(slot_id, content_type);
327 }
328
329 pub fn was_last_slot_reused(&self) -> Option<bool> {
337 self.state.was_last_slot_reused()
338 }
339}
340
341fn compose_subcompose_slot_content(holder: cranpose_core::CallbackHolder) {
342 cranpose_core::with_current_composer(|composer| {
343 let holder_for_recompose = holder.clone();
344 composer.set_recranpose_callback(move |_composer| {
345 compose_subcompose_slot_content(holder_for_recompose.clone());
346 });
347 });
348
349 let invoke = holder.clone_rc();
350 invoke();
351}
352
353pub type MeasurePolicy =
355 dyn for<'scope> Fn(&mut SubcomposeMeasureScopeImpl<'scope>, Constraints) -> MeasureResult;
356
357pub struct SubcomposeLayoutNode {
359 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
360 parent: Cell<Option<NodeId>>,
362 id: Cell<Option<NodeId>>,
364 needs_measure: Cell<bool>,
366 needs_layout: Cell<bool>,
367 needs_semantics: Cell<bool>,
368 needs_redraw: Cell<bool>,
369 needs_pointer_pass: Cell<bool>,
370 needs_focus_sync: Cell<bool>,
371 virtual_children_count: Cell<usize>,
372 layout_state: RefCell<LayoutState>,
374 modifier_slices_snapshot: RefCell<Rc<ModifierNodeSlices>>,
375 modifier_slices_dirty: Cell<bool>,
376}
377
378impl SubcomposeLayoutNode {
379 pub fn new(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
380 let inner = Rc::new(RefCell::new(SubcomposeLayoutNodeInner::new(measure_policy)));
381 let node = Self {
382 inner,
383 parent: Cell::new(None),
384 id: Cell::new(None),
385 needs_measure: Cell::new(true),
386 needs_layout: Cell::new(true),
387 needs_semantics: Cell::new(true),
388 needs_redraw: Cell::new(true),
389 needs_pointer_pass: Cell::new(false),
390 needs_focus_sync: Cell::new(false),
391 virtual_children_count: Cell::new(0),
392 layout_state: RefCell::new(LayoutState::default()),
393 modifier_slices_snapshot: RefCell::new(Rc::default()),
394 modifier_slices_dirty: Cell::new(true),
395 };
396 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
399 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
400 node.update_modifier_slices_cache();
401 node
402 }
403
404 pub fn with_content_type_policy(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
410 let mut inner_data = SubcomposeLayoutNodeInner::new(measure_policy);
411 inner_data
412 .state
413 .set_policy(Box::new(cranpose_core::ContentTypeReusePolicy::new()));
414 let inner = Rc::new(RefCell::new(inner_data));
415 let node = Self {
416 inner,
417 parent: Cell::new(None),
418 id: Cell::new(None),
419 needs_measure: Cell::new(true),
420 needs_layout: Cell::new(true),
421 needs_semantics: Cell::new(true),
422 needs_redraw: Cell::new(true),
423 needs_pointer_pass: Cell::new(false),
424 needs_focus_sync: Cell::new(false),
425 virtual_children_count: Cell::new(0),
426 layout_state: RefCell::new(LayoutState::default()),
427 modifier_slices_snapshot: RefCell::new(Rc::default()),
428 modifier_slices_dirty: Cell::new(true),
429 };
430 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
433 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
434 node.update_modifier_slices_cache();
435 node
436 }
437
438 pub fn handle(&self) -> SubcomposeLayoutNodeHandle {
439 SubcomposeLayoutNodeHandle {
440 inner: Rc::clone(&self.inner),
441 }
442 }
443
444 #[doc(hidden)]
445 pub fn debug_scope_ids_by_slot(&self) -> Vec<(u64, Vec<usize>)> {
446 self.inner.borrow().state.debug_scope_ids_by_slot()
447 }
448
449 #[doc(hidden)]
450 pub fn debug_slot_table_for_slot(
451 &self,
452 slot_id: cranpose_core::SlotId,
453 ) -> Option<Vec<cranpose_core::SlotDebugEntry>> {
454 self.inner.borrow().state.debug_slot_table_for_slot(slot_id)
455 }
456
457 #[doc(hidden)]
458 pub fn debug_slot_table_groups_for_slot(
459 &self,
460 slot_id: cranpose_core::SlotId,
461 ) -> Option<Vec<cranpose_core::subcompose::DebugSlotGroup>> {
462 self.inner
463 .borrow()
464 .state
465 .debug_slot_table_groups_for_slot(slot_id)
466 }
467
468 pub fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
469 let mut inner = self.inner.borrow_mut();
470 if Rc::ptr_eq(&inner.measure_policy, &policy) {
471 return;
472 }
473 inner.set_measure_policy(policy);
474 drop(inner);
475 self.invalidate_subcomposition();
476 }
477
478 pub fn set_modifier(&mut self, modifier: Modifier) {
479 let prev_caps = self.modifier_capabilities();
481 let (invalidations, modifier_changed) = {
483 let mut inner = self.inner.borrow_mut();
484 inner.set_modifier_collect(modifier)
485 };
486 self.dispatch_modifier_invalidations(&invalidations, prev_caps);
489 self.update_modifier_slices_cache();
490 if modifier_changed {
491 self.request_semantics_update();
492 }
493 }
494
495 fn update_modifier_slices_cache(&self) {
497 let inner = self.inner.borrow();
498 let mut snapshot = self.modifier_slices_snapshot.borrow_mut();
499 collect_modifier_slices_into(inner.modifier_chain.chain(), Rc::make_mut(&mut snapshot));
500 self.modifier_slices_dirty.set(false);
501 }
502
503 pub fn set_debug_modifiers(&mut self, enabled: bool) {
504 self.inner.borrow_mut().set_debug_modifiers(enabled);
505 }
506
507 pub fn modifier(&self) -> Modifier {
508 self.handle().modifier()
509 }
510
511 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
512 self.inner.borrow().resolved_modifiers
513 }
514
515 pub fn layout_state(&self) -> LayoutState {
517 self.layout_state.borrow().clone()
518 }
519
520 pub fn set_position(&self, position: Point) {
522 let mut state = self.layout_state.borrow_mut();
523 state.position = position;
524 state.is_placed = true;
525 }
526
527 pub fn set_measured_size(&self, size: Size) {
529 let mut state = self.layout_state.borrow_mut();
530 state.size = size;
531 }
532
533 pub fn clear_placed(&self) {
535 self.layout_state.borrow_mut().is_placed = false;
536 }
537
538 pub fn modifier_slices_snapshot(&self) -> Rc<ModifierNodeSlices> {
540 if self.modifier_slices_dirty.get() {
541 self.update_modifier_slices_cache();
542 }
543 self.modifier_slices_snapshot.borrow().clone()
544 }
545
546 pub fn state(&self) -> Ref<'_, SubcomposeState> {
547 Ref::map(self.inner.borrow(), |inner| &inner.state)
548 }
549
550 pub fn state_mut(&self) -> RefMut<'_, SubcomposeState> {
551 RefMut::map(self.inner.borrow_mut(), |inner| &mut inner.state)
552 }
553
554 pub fn invalidate_subcomposition(&self) {
555 self.inner.borrow().state.invalidate_scopes();
556 self.mark_needs_measure();
557 if let Some(id) = self.id.get() {
558 cranpose_core::bubble_measure_dirty_in_composer(id);
559 }
560 }
561
562 pub fn request_measure_recompose(&self) {
563 self.mark_needs_measure();
564 if let Some(id) = self.id.get() {
565 cranpose_core::bubble_measure_dirty_in_composer(id);
566 }
567 }
568
569 pub fn active_children(&self) -> Vec<NodeId> {
570 current_subcompose_children(&self.inner.borrow())
571 }
572
573 pub fn mark_needs_measure(&self) {
575 self.needs_measure.set(true);
576 self.needs_layout.set(true);
577 }
578
579 pub fn mark_needs_layout_flag(&self) {
581 self.needs_layout.set(true);
582 }
583
584 pub fn mark_needs_redraw(&self) {
586 self.needs_redraw.set(true);
587 if let Some(id) = self.id.get() {
588 crate::schedule_draw_repass(id);
589 }
590 crate::request_render_invalidation();
591 }
592
593 pub fn needs_measure(&self) -> bool {
595 self.needs_measure.get()
596 }
597
598 pub(crate) fn clear_needs_measure(&self) {
599 self.needs_measure.set(false);
600 }
601
602 pub(crate) fn clear_needs_layout(&self) {
603 self.needs_layout.set(false);
604 }
605
606 pub fn mark_needs_semantics(&self) {
608 self.needs_semantics.set(true);
609 }
610
611 pub fn needs_semantics_flag(&self) -> bool {
613 self.needs_semantics.get()
614 }
615
616 pub(crate) fn clear_needs_semantics(&self) {
617 self.needs_semantics.set(false);
618 }
619
620 #[cfg(test)]
621 pub(crate) fn clear_needs_semantics_for_tests(&self) {
622 self.clear_needs_semantics();
623 }
624
625 pub fn needs_redraw(&self) -> bool {
627 self.needs_redraw.get()
628 }
629
630 pub fn clear_needs_redraw(&self) {
631 self.needs_redraw.set(false);
632 }
633
634 pub fn mark_needs_pointer_pass(&self) {
636 self.needs_pointer_pass.set(true);
637 }
638
639 pub fn needs_pointer_pass(&self) -> bool {
641 self.needs_pointer_pass.get()
642 }
643
644 pub fn clear_needs_pointer_pass(&self) {
646 self.needs_pointer_pass.set(false);
647 }
648
649 pub fn mark_needs_focus_sync(&self) {
651 self.needs_focus_sync.set(true);
652 }
653
654 pub fn needs_focus_sync(&self) -> bool {
656 self.needs_focus_sync.get()
657 }
658
659 pub fn clear_needs_focus_sync(&self) {
661 self.needs_focus_sync.set(false);
662 }
663
664 fn request_semantics_update(&self) {
665 let already_dirty = self.needs_semantics.replace(true);
666 if already_dirty {
667 return;
668 }
669
670 if let Some(id) = self.id.get() {
671 cranpose_core::queue_semantics_invalidation(id);
672 }
673 }
674
675 pub fn modifier_capabilities(&self) -> NodeCapabilities {
677 self.inner.borrow().modifier_capabilities
678 }
679
680 pub fn has_layout_modifier_nodes(&self) -> bool {
681 self.modifier_capabilities()
682 .contains(NodeCapabilities::LAYOUT)
683 }
684
685 pub fn has_draw_modifier_nodes(&self) -> bool {
686 self.modifier_capabilities()
687 .contains(NodeCapabilities::DRAW)
688 }
689
690 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
691 self.modifier_capabilities()
692 .contains(NodeCapabilities::POINTER_INPUT)
693 }
694
695 pub fn has_semantics_modifier_nodes(&self) -> bool {
696 self.modifier_capabilities()
697 .contains(NodeCapabilities::SEMANTICS)
698 }
699
700 pub fn has_focus_modifier_nodes(&self) -> bool {
701 self.modifier_capabilities()
702 .contains(NodeCapabilities::FOCUS)
703 }
704
705 fn dispatch_modifier_invalidations(
712 &self,
713 invalidations: &[ModifierInvalidation],
714 prev_caps: NodeCapabilities,
715 ) {
716 let curr_caps = self.modifier_capabilities();
717 for invalidation in invalidations {
718 self.modifier_slices_dirty.set(true);
719 match invalidation.kind() {
720 InvalidationKind::Layout => {
721 if curr_caps.contains(NodeCapabilities::LAYOUT)
722 || prev_caps.contains(NodeCapabilities::LAYOUT)
723 {
724 self.mark_needs_measure();
725 }
726 }
727 InvalidationKind::Draw => {
728 if curr_caps.contains(NodeCapabilities::DRAW)
729 || prev_caps.contains(NodeCapabilities::DRAW)
730 {
731 self.mark_needs_redraw();
732 }
733 }
734 InvalidationKind::PointerInput => {
735 if curr_caps.contains(NodeCapabilities::POINTER_INPUT)
736 || prev_caps.contains(NodeCapabilities::POINTER_INPUT)
737 {
738 self.mark_needs_pointer_pass();
739 crate::request_pointer_invalidation();
740 if let Some(id) = self.id.get() {
742 crate::schedule_pointer_repass(id);
743 }
744 }
745 }
746 InvalidationKind::Semantics => {
747 self.request_semantics_update();
748 }
749 InvalidationKind::Focus => {
750 if curr_caps.contains(NodeCapabilities::FOCUS)
751 || prev_caps.contains(NodeCapabilities::FOCUS)
752 {
753 self.mark_needs_focus_sync();
754 crate::request_focus_invalidation();
755 if let Some(id) = self.id.get() {
757 crate::schedule_focus_invalidation(id);
758 }
759 }
760 }
761 }
762 }
763 }
764}
765
766impl cranpose_core::Node for SubcomposeLayoutNode {
767 fn mount(&mut self) {
768 let mut inner = self.inner.borrow_mut();
769 let (chain, mut context) = inner.modifier_chain.chain_and_context_mut();
770 chain.repair_chain();
771 chain.attach_nodes(&mut *context);
772 }
773
774 fn unmount(&mut self) {
775 self.inner
776 .borrow_mut()
777 .modifier_chain
778 .chain_mut()
779 .detach_nodes();
780 }
781
782 fn insert_child(&mut self, child: NodeId) {
783 let mut inner = self.inner.borrow_mut();
784 if inner.children.contains(&child) {
785 return;
786 }
787 if is_virtual_node(child) {
788 let count = self.virtual_children_count.get();
789 self.virtual_children_count.set(count + 1);
790 }
791 inner.children.push(child);
792 }
793
794 fn remove_child(&mut self, child: NodeId) {
795 let mut inner = self.inner.borrow_mut();
796 let before = inner.children.len();
797 inner.children.retain(|&id| id != child);
798 if inner.children.len() < before && is_virtual_node(child) {
799 let count = self.virtual_children_count.get();
800 if count > 0 {
801 self.virtual_children_count.set(count - 1);
802 }
803 }
804 }
805
806 fn move_child(&mut self, from: usize, to: usize) {
807 let mut inner = self.inner.borrow_mut();
808 if from == to || from >= inner.children.len() {
809 return;
810 }
811 let child = inner.children.remove(from);
812 let target = to.min(inner.children.len());
813 inner.children.insert(target, child);
814 }
815
816 fn update_children(&mut self, children: &[NodeId]) {
817 let mut inner = self.inner.borrow_mut();
818 inner.children.clear();
819 inner.children.extend_from_slice(children);
820 }
821
822 fn children(&self) -> Vec<NodeId> {
823 current_subcompose_children(&self.inner.borrow())
824 }
825
826 fn set_node_id(&mut self, id: NodeId) {
827 self.id.set(Some(id));
828 self.inner.borrow_mut().modifier_chain.set_node_id(Some(id));
829 }
830
831 fn on_attached_to_parent(&mut self, parent: NodeId) {
832 self.parent.set(Some(parent));
833 }
834
835 fn on_removed_from_parent(&mut self) {
836 self.parent.set(None);
837 }
838
839 fn parent(&self) -> Option<NodeId> {
840 self.parent.get()
841 }
842
843 fn mark_needs_layout(&self) {
844 self.needs_layout.set(true);
845 }
846
847 fn needs_layout(&self) -> bool {
848 self.needs_layout.get()
849 }
850
851 fn mark_needs_measure(&self) {
852 self.needs_measure.set(true);
853 self.needs_layout.set(true); }
855
856 fn needs_measure(&self) -> bool {
857 self.needs_measure.get()
858 }
859
860 fn mark_needs_semantics(&self) {
861 self.needs_semantics.set(true);
862 }
863
864 fn needs_semantics(&self) -> bool {
865 self.needs_semantics.get()
866 }
867
868 fn set_parent_for_bubbling(&mut self, parent: NodeId) {
870 self.parent.set(Some(parent));
871 }
872}
873
874#[derive(Clone)]
875pub struct SubcomposeLayoutNodeHandle {
876 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
877}
878
879impl SubcomposeLayoutNodeHandle {
880 pub fn modifier(&self) -> Modifier {
881 self.inner.borrow().modifier.clone()
882 }
883
884 pub fn layout_properties(&self) -> crate::modifier::LayoutProperties {
885 self.resolved_modifiers().layout_properties()
886 }
887
888 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
889 self.inner.borrow().resolved_modifiers
890 }
891
892 pub fn total_offset(&self) -> Point {
893 self.resolved_modifiers().offset()
894 }
895
896 pub fn modifier_capabilities(&self) -> NodeCapabilities {
897 self.inner.borrow().modifier_capabilities
898 }
899
900 pub fn has_layout_modifier_nodes(&self) -> bool {
901 self.modifier_capabilities()
902 .contains(NodeCapabilities::LAYOUT)
903 }
904
905 pub fn has_draw_modifier_nodes(&self) -> bool {
906 self.modifier_capabilities()
907 .contains(NodeCapabilities::DRAW)
908 }
909
910 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
911 self.modifier_capabilities()
912 .contains(NodeCapabilities::POINTER_INPUT)
913 }
914
915 pub fn has_semantics_modifier_nodes(&self) -> bool {
916 self.modifier_capabilities()
917 .contains(NodeCapabilities::SEMANTICS)
918 }
919
920 pub fn has_focus_modifier_nodes(&self) -> bool {
921 self.modifier_capabilities()
922 .contains(NodeCapabilities::FOCUS)
923 }
924
925 pub fn set_debug_modifiers(&self, enabled: bool) {
926 self.inner.borrow_mut().set_debug_modifiers(enabled);
927 }
928
929 pub fn measure<'a>(
930 &self,
931 composer: &Composer,
932 node_id: NodeId,
933 constraints: Constraints,
934 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
935 error: &'a RefCell<Option<NodeError>>,
936 ) -> Result<MeasureResult, NodeError> {
937 let (policy, mut state, slots_host) = {
938 let mut inner = self.inner.borrow_mut();
939 let policy = Rc::clone(&inner.measure_policy);
940 let state = std::mem::take(&mut inner.state);
941 let slots_host = Rc::clone(&inner.slots);
942 (policy, state, slots_host)
943 };
944 state.begin_pass();
945
946 let previous = composer.phase();
947 if !matches!(previous, Phase::Measure | Phase::Layout) {
948 composer.enter_phase(Phase::Measure);
949 }
950
951 let constraints_copy = constraints;
952 let (result, _) =
961 composer.subcompose_slot(&slots_host, Some(node_id), |inner_composer| {
962 let mut scope = SubcomposeMeasureScopeImpl::new(
963 inner_composer.clone(),
964 &mut state,
965 constraints_copy,
966 measurer,
967 error,
968 self.clone(), node_id, );
971 (policy)(&mut scope, constraints_copy)
972 })?;
973
974 state.finish_pass();
975
976 if previous != composer.phase() {
977 composer.enter_phase(previous);
978 }
979
980 {
981 let mut inner = self.inner.borrow_mut();
982 inner.state = state;
983
984 inner.last_placements = result.placements.iter().map(|p| p.node_id).collect();
989 }
990
991 Ok(result)
992 }
993
994 pub fn set_active_children<I>(&self, children: I)
995 where
996 I: IntoIterator<Item = NodeId>,
997 {
998 let mut inner = self.inner.borrow_mut();
999 inner.children.clear();
1000 inner.children.extend(children);
1001 }
1002}
1003
1004fn current_subcompose_children(inner: &SubcomposeLayoutNodeInner) -> Vec<NodeId> {
1005 if !inner.last_placements.is_empty() {
1006 inner.last_placements.clone()
1007 } else {
1008 inner.children.clone()
1009 }
1010}
1011
1012struct SubcomposeLayoutNodeInner {
1013 modifier: Modifier,
1014 modifier_chain: ModifierChainHandle,
1015 resolved_modifiers: ResolvedModifiers,
1016 modifier_capabilities: NodeCapabilities,
1017 state: SubcomposeState,
1018 measure_policy: Rc<MeasurePolicy>,
1019 children: Vec<NodeId>,
1020 slots: Rc<SlotsHost>,
1021 debug_modifiers: bool,
1022 virtual_nodes: HashMap<NodeId, Rc<LayoutNode>>,
1024 last_placements: Vec<NodeId>,
1027}
1028
1029impl SubcomposeLayoutNodeInner {
1030 fn new(measure_policy: Rc<MeasurePolicy>) -> Self {
1031 Self {
1032 modifier: Modifier::empty(),
1033 modifier_chain: ModifierChainHandle::new(),
1034 resolved_modifiers: ResolvedModifiers::default(),
1035 modifier_capabilities: NodeCapabilities::default(),
1036 state: SubcomposeState::default(),
1037 measure_policy,
1038 children: Vec::new(),
1039 slots: Rc::new(SlotsHost::new(SlotTable::default())),
1040 debug_modifiers: false,
1041 virtual_nodes: HashMap::new(),
1042 last_placements: Vec::new(),
1043 }
1044 }
1045
1046 fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
1047 self.measure_policy = policy;
1048 if let Err(err) = self.slots.reset() {
1053 log::error!(
1054 "failed to reset root measurement slots after measure policy update: {err}"
1055 );
1056 }
1057 }
1058
1059 fn set_modifier_collect(&mut self, modifier: Modifier) -> (Vec<ModifierInvalidation>, bool) {
1062 let modifier_changed = !self.modifier.structural_eq(&modifier);
1063 self.modifier = modifier;
1064 self.modifier_chain.set_debug_logging(self.debug_modifiers);
1065 let modifier_local_invalidations = self.modifier_chain.update(&self.modifier);
1066 self.resolved_modifiers = self.modifier_chain.resolved_modifiers();
1067 self.modifier_capabilities = self.modifier_chain.capabilities();
1068
1069 let mut invalidations = self.modifier_chain.take_invalidations();
1071 invalidations.extend(modifier_local_invalidations);
1072
1073 (invalidations, modifier_changed)
1074 }
1075
1076 fn set_debug_modifiers(&mut self, enabled: bool) {
1077 self.debug_modifiers = enabled;
1078 self.modifier_chain.set_debug_logging(enabled);
1079 }
1080}
1081
1082#[cfg(test)]
1083#[path = "tests/subcompose_layout_tests.rs"]
1084mod tests;