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_buffer: RefCell<ModifierNodeSlices>,
376 modifier_slices_snapshot: RefCell<Rc<ModifierNodeSlices>>,
377 modifier_slices_dirty: Cell<bool>,
378}
379
380impl SubcomposeLayoutNode {
381 pub fn new(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
382 let inner = Rc::new(RefCell::new(SubcomposeLayoutNodeInner::new(measure_policy)));
383 let node = Self {
384 inner,
385 parent: Cell::new(None),
386 id: Cell::new(None),
387 needs_measure: Cell::new(true),
388 needs_layout: Cell::new(true),
389 needs_semantics: Cell::new(true),
390 needs_redraw: Cell::new(true),
391 needs_pointer_pass: Cell::new(false),
392 needs_focus_sync: Cell::new(false),
393 virtual_children_count: Cell::new(0),
394 layout_state: RefCell::new(LayoutState::default()),
395 modifier_slices_buffer: RefCell::new(ModifierNodeSlices::default()),
396 modifier_slices_snapshot: RefCell::new(Rc::default()),
397 modifier_slices_dirty: Cell::new(true),
398 };
399 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
402 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
403 node.update_modifier_slices_cache();
404 node
405 }
406
407 pub fn with_content_type_policy(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
413 let mut inner_data = SubcomposeLayoutNodeInner::new(measure_policy);
414 inner_data
415 .state
416 .set_policy(Box::new(cranpose_core::ContentTypeReusePolicy::new()));
417 let inner = Rc::new(RefCell::new(inner_data));
418 let node = Self {
419 inner,
420 parent: Cell::new(None),
421 id: Cell::new(None),
422 needs_measure: Cell::new(true),
423 needs_layout: Cell::new(true),
424 needs_semantics: Cell::new(true),
425 needs_redraw: Cell::new(true),
426 needs_pointer_pass: Cell::new(false),
427 needs_focus_sync: Cell::new(false),
428 virtual_children_count: Cell::new(0),
429 layout_state: RefCell::new(LayoutState::default()),
430 modifier_slices_buffer: RefCell::new(ModifierNodeSlices::default()),
431 modifier_slices_snapshot: RefCell::new(Rc::default()),
432 modifier_slices_dirty: Cell::new(true),
433 };
434 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
437 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
438 node.update_modifier_slices_cache();
439 node
440 }
441
442 pub fn handle(&self) -> SubcomposeLayoutNodeHandle {
443 SubcomposeLayoutNodeHandle {
444 inner: Rc::clone(&self.inner),
445 }
446 }
447
448 #[doc(hidden)]
449 pub fn debug_scope_ids_by_slot(&self) -> Vec<(u64, Vec<usize>)> {
450 self.inner.borrow().state.debug_scope_ids_by_slot()
451 }
452
453 #[doc(hidden)]
454 pub fn debug_slot_table_for_slot(
455 &self,
456 slot_id: cranpose_core::SlotId,
457 ) -> Option<Vec<(usize, String)>> {
458 self.inner.borrow().state.debug_slot_table_for_slot(slot_id)
459 }
460
461 #[doc(hidden)]
462 pub fn debug_slot_table_groups_for_slot(
463 &self,
464 slot_id: cranpose_core::SlotId,
465 ) -> Option<Vec<cranpose_core::subcompose::DebugSlotGroup>> {
466 self.inner
467 .borrow()
468 .state
469 .debug_slot_table_groups_for_slot(slot_id)
470 }
471
472 pub fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
473 let mut inner = self.inner.borrow_mut();
474 if Rc::ptr_eq(&inner.measure_policy, &policy) {
475 return;
476 }
477 inner.set_measure_policy(policy);
478 drop(inner);
479 self.invalidate_subcomposition();
480 }
481
482 pub fn set_modifier(&mut self, modifier: Modifier) {
483 let prev_caps = self.modifier_capabilities();
485 let (invalidations, modifier_changed) = {
487 let mut inner = self.inner.borrow_mut();
488 inner.set_modifier_collect(modifier)
489 };
490 self.dispatch_modifier_invalidations(&invalidations, prev_caps);
493 self.update_modifier_slices_cache();
494 if modifier_changed {
495 self.mark_needs_measure();
496 self.request_semantics_update();
497 }
498 }
499
500 fn update_modifier_slices_cache(&self) {
502 let inner = self.inner.borrow();
503 let mut buffer = self.modifier_slices_buffer.borrow_mut();
504 collect_modifier_slices_into(inner.modifier_chain.chain(), &mut buffer);
505 *self.modifier_slices_snapshot.borrow_mut() = Rc::new(buffer.clone());
506 self.modifier_slices_dirty.set(false);
507 }
508
509 pub fn set_debug_modifiers(&mut self, enabled: bool) {
510 self.inner.borrow_mut().set_debug_modifiers(enabled);
511 }
512
513 pub fn modifier(&self) -> Modifier {
514 self.handle().modifier()
515 }
516
517 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
518 self.inner.borrow().resolved_modifiers
519 }
520
521 pub fn layout_state(&self) -> LayoutState {
523 self.layout_state.borrow().clone()
524 }
525
526 pub fn set_position(&self, position: Point) {
528 let mut state = self.layout_state.borrow_mut();
529 state.position = position;
530 state.is_placed = true;
531 }
532
533 pub fn set_measured_size(&self, size: Size) {
535 let mut state = self.layout_state.borrow_mut();
536 state.size = size;
537 }
538
539 pub fn clear_placed(&self) {
541 self.layout_state.borrow_mut().is_placed = false;
542 }
543
544 pub fn modifier_slices_snapshot(&self) -> Rc<ModifierNodeSlices> {
546 if self.modifier_slices_dirty.get() {
547 self.update_modifier_slices_cache();
548 }
549 self.modifier_slices_snapshot.borrow().clone()
550 }
551
552 pub fn state(&self) -> Ref<'_, SubcomposeState> {
553 Ref::map(self.inner.borrow(), |inner| &inner.state)
554 }
555
556 pub fn state_mut(&self) -> RefMut<'_, SubcomposeState> {
557 RefMut::map(self.inner.borrow_mut(), |inner| &mut inner.state)
558 }
559
560 pub fn invalidate_subcomposition(&self) {
561 self.inner.borrow().state.invalidate_scopes();
562 self.mark_needs_measure();
563 if let Some(id) = self.id.get() {
564 cranpose_core::bubble_measure_dirty_in_composer(id);
565 }
566 }
567
568 pub fn request_measure_recompose(&self) {
569 self.mark_needs_measure();
570 if let Some(id) = self.id.get() {
571 cranpose_core::bubble_measure_dirty_in_composer(id);
572 }
573 }
574
575 pub fn active_children(&self) -> Vec<NodeId> {
576 current_subcompose_children(&self.inner.borrow())
577 }
578
579 pub fn mark_needs_measure(&self) {
581 self.needs_measure.set(true);
582 self.needs_layout.set(true);
583 }
584
585 pub fn mark_needs_layout_flag(&self) {
587 self.needs_layout.set(true);
588 }
589
590 pub fn mark_needs_redraw(&self) {
592 self.needs_redraw.set(true);
593 if let Some(id) = self.id.get() {
594 crate::schedule_draw_repass(id);
595 }
596 crate::request_render_invalidation();
597 }
598
599 pub fn needs_measure(&self) -> bool {
601 self.needs_measure.get()
602 }
603
604 pub(crate) fn clear_needs_measure(&self) {
605 self.needs_measure.set(false);
606 }
607
608 pub(crate) fn clear_needs_layout(&self) {
609 self.needs_layout.set(false);
610 }
611
612 pub fn mark_needs_semantics(&self) {
614 self.needs_semantics.set(true);
615 }
616
617 pub fn needs_semantics_flag(&self) -> bool {
619 self.needs_semantics.get()
620 }
621
622 #[cfg(test)]
623 pub(crate) fn clear_needs_semantics_for_tests(&self) {
624 self.needs_semantics.set(false);
625 }
626
627 pub fn needs_redraw(&self) -> bool {
629 self.needs_redraw.get()
630 }
631
632 pub fn clear_needs_redraw(&self) {
633 self.needs_redraw.set(false);
634 }
635
636 pub fn mark_needs_pointer_pass(&self) {
638 self.needs_pointer_pass.set(true);
639 }
640
641 pub fn needs_pointer_pass(&self) -> bool {
643 self.needs_pointer_pass.get()
644 }
645
646 pub fn clear_needs_pointer_pass(&self) {
648 self.needs_pointer_pass.set(false);
649 }
650
651 pub fn mark_needs_focus_sync(&self) {
653 self.needs_focus_sync.set(true);
654 }
655
656 pub fn needs_focus_sync(&self) -> bool {
658 self.needs_focus_sync.get()
659 }
660
661 pub fn clear_needs_focus_sync(&self) {
663 self.needs_focus_sync.set(false);
664 }
665
666 fn request_semantics_update(&self) {
667 let already_dirty = self.needs_semantics.replace(true);
668 if already_dirty {
669 return;
670 }
671
672 if let Some(id) = self.id.get() {
673 cranpose_core::queue_semantics_invalidation(id);
674 }
675 }
676
677 pub fn modifier_capabilities(&self) -> NodeCapabilities {
679 self.inner.borrow().modifier_capabilities
680 }
681
682 pub fn has_layout_modifier_nodes(&self) -> bool {
683 self.modifier_capabilities()
684 .contains(NodeCapabilities::LAYOUT)
685 }
686
687 pub fn has_draw_modifier_nodes(&self) -> bool {
688 self.modifier_capabilities()
689 .contains(NodeCapabilities::DRAW)
690 }
691
692 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
693 self.modifier_capabilities()
694 .contains(NodeCapabilities::POINTER_INPUT)
695 }
696
697 pub fn has_semantics_modifier_nodes(&self) -> bool {
698 self.modifier_capabilities()
699 .contains(NodeCapabilities::SEMANTICS)
700 }
701
702 pub fn has_focus_modifier_nodes(&self) -> bool {
703 self.modifier_capabilities()
704 .contains(NodeCapabilities::FOCUS)
705 }
706
707 fn dispatch_modifier_invalidations(
714 &self,
715 invalidations: &[ModifierInvalidation],
716 prev_caps: NodeCapabilities,
717 ) {
718 let curr_caps = self.modifier_capabilities();
719 for invalidation in invalidations {
720 self.modifier_slices_dirty.set(true);
721 match invalidation.kind() {
722 InvalidationKind::Layout => {
723 if curr_caps.contains(NodeCapabilities::LAYOUT)
724 || prev_caps.contains(NodeCapabilities::LAYOUT)
725 {
726 self.mark_needs_measure();
727 }
728 }
729 InvalidationKind::Draw => {
730 if curr_caps.contains(NodeCapabilities::DRAW)
731 || prev_caps.contains(NodeCapabilities::DRAW)
732 {
733 self.mark_needs_redraw();
734 }
735 }
736 InvalidationKind::PointerInput => {
737 if curr_caps.contains(NodeCapabilities::POINTER_INPUT)
738 || prev_caps.contains(NodeCapabilities::POINTER_INPUT)
739 {
740 self.mark_needs_pointer_pass();
741 crate::request_pointer_invalidation();
742 if let Some(id) = self.id.get() {
744 crate::schedule_pointer_repass(id);
745 }
746 }
747 }
748 InvalidationKind::Semantics => {
749 self.request_semantics_update();
750 }
751 InvalidationKind::Focus => {
752 if curr_caps.contains(NodeCapabilities::FOCUS)
753 || prev_caps.contains(NodeCapabilities::FOCUS)
754 {
755 self.mark_needs_focus_sync();
756 crate::request_focus_invalidation();
757 if let Some(id) = self.id.get() {
759 crate::schedule_focus_invalidation(id);
760 }
761 }
762 }
763 }
764 }
765 }
766}
767
768impl cranpose_core::Node for SubcomposeLayoutNode {
769 fn mount(&mut self) {
770 let mut inner = self.inner.borrow_mut();
771 let (chain, mut context) = inner.modifier_chain.chain_and_context_mut();
772 chain.repair_chain();
773 chain.attach_nodes(&mut *context);
774 }
775
776 fn unmount(&mut self) {
777 self.inner
778 .borrow_mut()
779 .modifier_chain
780 .chain_mut()
781 .detach_nodes();
782 }
783
784 fn insert_child(&mut self, child: NodeId) {
785 let mut inner = self.inner.borrow_mut();
786 if inner.children.contains(&child) {
787 return;
788 }
789 if is_virtual_node(child) {
790 let count = self.virtual_children_count.get();
791 self.virtual_children_count.set(count + 1);
792 }
793 inner.children.push(child);
794 }
795
796 fn remove_child(&mut self, child: NodeId) {
797 let mut inner = self.inner.borrow_mut();
798 let before = inner.children.len();
799 inner.children.retain(|&id| id != child);
800 if inner.children.len() < before && is_virtual_node(child) {
801 let count = self.virtual_children_count.get();
802 if count > 0 {
803 self.virtual_children_count.set(count - 1);
804 }
805 }
806 }
807
808 fn move_child(&mut self, from: usize, to: usize) {
809 let mut inner = self.inner.borrow_mut();
810 if from == to || from >= inner.children.len() {
811 return;
812 }
813 let child = inner.children.remove(from);
814 let target = to.min(inner.children.len());
815 inner.children.insert(target, child);
816 }
817
818 fn update_children(&mut self, children: &[NodeId]) {
819 let mut inner = self.inner.borrow_mut();
820 inner.children.clear();
821 inner.children.extend_from_slice(children);
822 }
823
824 fn children(&self) -> Vec<NodeId> {
825 current_subcompose_children(&self.inner.borrow())
826 }
827
828 fn set_node_id(&mut self, id: NodeId) {
829 self.id.set(Some(id));
830 self.inner.borrow_mut().modifier_chain.set_node_id(Some(id));
831 }
832
833 fn on_attached_to_parent(&mut self, parent: NodeId) {
834 self.parent.set(Some(parent));
835 }
836
837 fn on_removed_from_parent(&mut self) {
838 self.parent.set(None);
839 }
840
841 fn parent(&self) -> Option<NodeId> {
842 self.parent.get()
843 }
844
845 fn mark_needs_layout(&self) {
846 self.needs_layout.set(true);
847 }
848
849 fn needs_layout(&self) -> bool {
850 self.needs_layout.get()
851 }
852
853 fn mark_needs_measure(&self) {
854 self.needs_measure.set(true);
855 self.needs_layout.set(true); }
857
858 fn needs_measure(&self) -> bool {
859 self.needs_measure.get()
860 }
861
862 fn mark_needs_semantics(&self) {
863 self.needs_semantics.set(true);
864 }
865
866 fn needs_semantics(&self) -> bool {
867 self.needs_semantics.get()
868 }
869
870 fn set_parent_for_bubbling(&mut self, parent: NodeId) {
872 self.parent.set(Some(parent));
873 }
874}
875
876#[derive(Clone)]
877pub struct SubcomposeLayoutNodeHandle {
878 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
879}
880
881impl SubcomposeLayoutNodeHandle {
882 pub fn modifier(&self) -> Modifier {
883 self.inner.borrow().modifier.clone()
884 }
885
886 pub fn layout_properties(&self) -> crate::modifier::LayoutProperties {
887 self.resolved_modifiers().layout_properties()
888 }
889
890 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
891 self.inner.borrow().resolved_modifiers
892 }
893
894 pub fn total_offset(&self) -> Point {
895 self.resolved_modifiers().offset()
896 }
897
898 pub fn modifier_capabilities(&self) -> NodeCapabilities {
899 self.inner.borrow().modifier_capabilities
900 }
901
902 pub fn has_layout_modifier_nodes(&self) -> bool {
903 self.modifier_capabilities()
904 .contains(NodeCapabilities::LAYOUT)
905 }
906
907 pub fn has_draw_modifier_nodes(&self) -> bool {
908 self.modifier_capabilities()
909 .contains(NodeCapabilities::DRAW)
910 }
911
912 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
913 self.modifier_capabilities()
914 .contains(NodeCapabilities::POINTER_INPUT)
915 }
916
917 pub fn has_semantics_modifier_nodes(&self) -> bool {
918 self.modifier_capabilities()
919 .contains(NodeCapabilities::SEMANTICS)
920 }
921
922 pub fn has_focus_modifier_nodes(&self) -> bool {
923 self.modifier_capabilities()
924 .contains(NodeCapabilities::FOCUS)
925 }
926
927 pub fn set_debug_modifiers(&self, enabled: bool) {
928 self.inner.borrow_mut().set_debug_modifiers(enabled);
929 }
930
931 pub fn measure<'a>(
932 &self,
933 composer: &Composer,
934 node_id: NodeId,
935 constraints: Constraints,
936 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
937 error: &'a RefCell<Option<NodeError>>,
938 ) -> Result<MeasureResult, NodeError> {
939 let (policy, mut state, slots_host) = {
940 let mut inner = self.inner.borrow_mut();
941 let policy = Rc::clone(&inner.measure_policy);
942 let state = std::mem::take(&mut inner.state);
943 let slots_host = Rc::clone(&inner.slots);
944 (policy, state, slots_host)
945 };
946 state.begin_pass();
947
948 let previous = composer.phase();
949 if !matches!(previous, Phase::Measure | Phase::Layout) {
950 composer.enter_phase(Phase::Measure);
951 }
952
953 let constraints_copy = constraints;
954 let (result, _) =
963 composer.subcompose_slot(&slots_host, Some(node_id), |inner_composer| {
964 let mut scope = SubcomposeMeasureScopeImpl::new(
965 inner_composer.clone(),
966 &mut state,
967 constraints_copy,
968 measurer,
969 error,
970 self.clone(), node_id, );
973 (policy)(&mut scope, constraints_copy)
974 })?;
975
976 state.finish_pass();
977
978 if previous != composer.phase() {
979 composer.enter_phase(previous);
980 }
981
982 {
983 let mut inner = self.inner.borrow_mut();
984 inner.state = state;
985
986 inner.last_placements = result.placements.iter().map(|p| p.node_id).collect();
991 }
992
993 Ok(result)
994 }
995
996 pub fn set_active_children<I>(&self, children: I)
997 where
998 I: IntoIterator<Item = NodeId>,
999 {
1000 let mut inner = self.inner.borrow_mut();
1001 inner.children.clear();
1002 inner.children.extend(children);
1003 }
1004}
1005
1006fn current_subcompose_children(inner: &SubcomposeLayoutNodeInner) -> Vec<NodeId> {
1007 if !inner.last_placements.is_empty() {
1008 inner.last_placements.clone()
1009 } else {
1010 inner.children.clone()
1011 }
1012}
1013
1014struct SubcomposeLayoutNodeInner {
1015 modifier: Modifier,
1016 modifier_chain: ModifierChainHandle,
1017 resolved_modifiers: ResolvedModifiers,
1018 modifier_capabilities: NodeCapabilities,
1019 state: SubcomposeState,
1020 measure_policy: Rc<MeasurePolicy>,
1021 children: Vec<NodeId>,
1022 slots: Rc<SlotsHost>,
1023 debug_modifiers: bool,
1024 virtual_nodes: HashMap<NodeId, Rc<LayoutNode>>,
1026 last_placements: Vec<NodeId>,
1029}
1030
1031impl SubcomposeLayoutNodeInner {
1032 fn new(measure_policy: Rc<MeasurePolicy>) -> Self {
1033 Self {
1034 modifier: Modifier::empty(),
1035 modifier_chain: ModifierChainHandle::new(),
1036 resolved_modifiers: ResolvedModifiers::default(),
1037 modifier_capabilities: NodeCapabilities::default(),
1038 state: SubcomposeState::default(),
1039 measure_policy,
1040 children: Vec::new(),
1041 slots: Rc::new(SlotsHost::new(SlotTable::default())),
1042 debug_modifiers: false,
1043 virtual_nodes: HashMap::new(),
1044 last_placements: Vec::new(),
1045 }
1046 }
1047
1048 fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
1049 self.measure_policy = policy;
1050 self.slots.reset();
1055 }
1056
1057 fn set_modifier_collect(&mut self, modifier: Modifier) -> (Vec<ModifierInvalidation>, bool) {
1060 let modifier_changed = !self.modifier.structural_eq(&modifier);
1061 self.modifier = modifier;
1062 self.modifier_chain.set_debug_logging(self.debug_modifiers);
1063 let modifier_local_invalidations = self.modifier_chain.update(&self.modifier);
1064 self.resolved_modifiers = self.modifier_chain.resolved_modifiers();
1065 self.modifier_capabilities = self.modifier_chain.capabilities();
1066
1067 let mut invalidations = self.modifier_chain.take_invalidations();
1069 invalidations.extend(modifier_local_invalidations);
1070
1071 (invalidations, modifier_changed)
1072 }
1073
1074 fn set_debug_modifiers(&mut self, enabled: bool) {
1075 self.debug_modifiers = enabled;
1076 self.modifier_chain.set_debug_logging(enabled);
1077 }
1078}
1079
1080#[cfg(test)]
1081#[path = "tests/subcompose_layout_tests.rs"]
1082mod tests;