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};
8use indexmap::IndexSet;
9
10use crate::modifier::{Modifier, ModifierChainHandle, Point, ResolvedModifiers, Size};
11use crate::widgets::nodes::{
12 allocate_virtual_node_id, is_virtual_node, register_layout_node, LayoutNode,
13};
14
15use cranpose_foundation::{InvalidationKind, ModifierInvalidation, NodeCapabilities};
16
17pub use cranpose_ui_layout::{Constraints, MeasureResult, Placement};
18
19#[derive(Clone, Copy, Debug)]
24pub struct SubcomposeChild {
25 node_id: NodeId,
26 measured_size: Option<Size>,
29}
30
31impl SubcomposeChild {
32 pub fn new(node_id: NodeId) -> Self {
33 Self {
34 node_id,
35 measured_size: None,
36 }
37 }
38
39 pub fn with_size(node_id: NodeId, size: Size) -> Self {
41 Self {
42 node_id,
43 measured_size: Some(size),
44 }
45 }
46
47 pub fn node_id(&self) -> NodeId {
48 self.node_id
49 }
50
51 pub fn size(&self) -> Size {
56 self.measured_size.unwrap_or(Size {
57 width: 0.0,
58 height: 0.0,
59 })
60 }
61
62 pub fn width(&self) -> f32 {
64 self.size().width
65 }
66
67 pub fn height(&self) -> f32 {
69 self.size().height
70 }
71
72 pub fn set_size(&mut self, size: Size) {
74 self.measured_size = Some(size);
75 }
76}
77
78impl PartialEq for SubcomposeChild {
79 fn eq(&self, other: &Self) -> bool {
80 self.node_id == other.node_id
81 }
82}
83
84#[derive(Clone, Copy, Debug)]
86pub struct SubcomposePlaceable {
87 node_id: NodeId,
88 size: Size,
89}
90
91impl SubcomposePlaceable {
92 pub fn new(node_id: NodeId, size: Size) -> Self {
93 Self { node_id, size }
94 }
95}
96
97impl cranpose_ui_layout::Placeable for SubcomposePlaceable {
98 fn place(&self, _x: f32, _y: f32) {
99 }
101
102 fn width(&self) -> f32 {
103 self.size.width
104 }
105
106 fn height(&self) -> f32 {
107 self.size.height
108 }
109
110 fn node_id(&self) -> NodeId {
111 self.node_id
112 }
113}
114
115pub trait SubcomposeLayoutScope {
117 fn constraints(&self) -> Constraints;
118
119 fn layout<I>(&mut self, width: f32, height: f32, placements: I) -> MeasureResult
120 where
121 I: IntoIterator<Item = Placement>,
122 {
123 MeasureResult::new(Size { width, height }, placements.into_iter().collect())
124 }
125}
126
127pub trait SubcomposeMeasureScope: SubcomposeLayoutScope {
129 fn subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<SubcomposeChild>
130 where
131 Content: FnOnce();
132
133 fn measure(&mut self, child: SubcomposeChild, constraints: Constraints) -> SubcomposePlaceable;
135
136 fn node_has_no_parent(&self, node_id: NodeId) -> bool;
139}
140
141pub struct SubcomposeMeasureScopeImpl<'a> {
143 composer: Composer,
144 state: &'a mut SubcomposeState,
145 constraints: Constraints,
146 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
147 error: Rc<RefCell<Option<NodeError>>>,
148 parent_handle: SubcomposeLayoutNodeHandle,
149 root_id: NodeId,
150}
151
152impl<'a> SubcomposeMeasureScopeImpl<'a> {
153 pub fn new(
154 composer: Composer,
155 state: &'a mut SubcomposeState,
156 constraints: Constraints,
157 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
158 error: Rc<RefCell<Option<NodeError>>>,
159
160 parent_handle: SubcomposeLayoutNodeHandle,
161 root_id: NodeId,
162 ) -> Self {
163 Self {
164 composer,
165 state,
166 constraints,
167 measurer,
168 error,
169 parent_handle,
170 root_id,
171 }
172 }
173
174 fn record_error(&self, err: NodeError) {
175 let mut slot = self.error.borrow_mut();
176 if slot.is_none() {
177 eprintln!("[SubcomposeLayout] Error suppressed: {:?}", err);
178 *slot = Some(err);
179 }
180 }
181
182 fn perform_subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<NodeId>
183 where
184 Content: FnOnce(),
185 {
186 let mut inner = self.parent_handle.inner.borrow_mut();
187
188 let (virtual_node_id, is_reused) =
190 if let Some(node_id) = self.state.take_node_from_reusables(slot_id) {
191 (node_id, true)
192 } else {
193 let id = allocate_virtual_node_id();
194 let node = LayoutNode::new_virtual();
195 if let Err(e) = self
199 .composer
200 .register_virtual_node(id, Box::new(node.clone()))
201 {
202 eprintln!(
203 "[Subcompose] Failed to register virtual node {}: {:?}",
204 id, e
205 );
206 }
207 register_layout_node(id, &node);
208
209 inner.virtual_nodes.insert(id, Rc::new(node));
210 inner.children.insert(id);
211 (id, false)
212 };
213
214 if let Some(v_node) = inner.virtual_nodes.get(&virtual_node_id) {
216 v_node.set_parent(self.root_id);
217 }
218
219 drop(inner);
220
221 if is_reused {
225 self.composer.clear_node_children(virtual_node_id);
226 }
227
228 let slot_host = self.state.get_or_create_slots(slot_id);
229 let _ = self
230 .composer
231 .subcompose_slot(&slot_host, Some(virtual_node_id), |_| content());
232
233 self.state.register_active(slot_id, &[virtual_node_id], &[]);
234
235 self.composer.get_node_children(virtual_node_id)
239 }
240}
241
242impl<'a> SubcomposeLayoutScope for SubcomposeMeasureScopeImpl<'a> {
243 fn constraints(&self) -> Constraints {
244 self.constraints
245 }
246}
247
248impl<'a> SubcomposeMeasureScope for SubcomposeMeasureScopeImpl<'a> {
249 fn subcompose<Content>(&mut self, slot_id: SlotId, content: Content) -> Vec<SubcomposeChild>
250 where
251 Content: FnOnce(),
252 {
253 let nodes = self.perform_subcompose(slot_id, content);
254 nodes.into_iter().map(SubcomposeChild::new).collect()
255 }
256
257 fn measure(&mut self, child: SubcomposeChild, constraints: Constraints) -> SubcomposePlaceable {
258 if self.error.borrow().is_some() {
259 return SubcomposePlaceable::new(child.node_id, Size::default());
261 }
262
263 if let Err(err) = self.composer.apply_pending_commands() {
264 self.record_error(err);
265 return SubcomposePlaceable::new(child.node_id, Size::default());
266 }
267
268 let size = (self.measurer)(child.node_id, constraints);
269 SubcomposePlaceable::new(child.node_id, size)
270 }
271
272 fn node_has_no_parent(&self, node_id: NodeId) -> bool {
273 self.composer.node_has_no_parent(node_id)
274 }
275}
276
277impl<'a> SubcomposeMeasureScopeImpl<'a> {
278 pub fn subcompose_with_size<Content, F>(
283 &mut self,
284 slot_id: SlotId,
285 content: Content,
286 estimate_size: F,
287 ) -> Vec<SubcomposeChild>
288 where
289 Content: FnOnce(),
290 F: Fn(usize) -> Size,
291 {
292 let nodes = self.perform_subcompose(slot_id, content);
293 nodes
294 .into_iter()
295 .enumerate()
296 .map(|(i, node_id)| SubcomposeChild::with_size(node_id, estimate_size(i)))
297 .collect()
298 }
299
300 pub fn active_slots_count(&self) -> usize {
304 self.state.active_slots_count()
305 }
306
307 pub fn reusable_slots_count(&self) -> usize {
311 self.state.reusable_slots_count()
312 }
313
314 pub fn register_content_type(&mut self, slot_id: SlotId, content_type: u64) {
320 self.state.register_content_type(slot_id, content_type);
321 }
322
323 pub fn update_content_type(&mut self, slot_id: SlotId, content_type: Option<u64>) {
329 self.state.update_content_type(slot_id, content_type);
330 }
331
332 pub fn was_last_slot_reused(&self) -> Option<bool> {
340 self.state.was_last_slot_reused()
341 }
342}
343
344pub type MeasurePolicy =
346 dyn for<'scope> Fn(&mut SubcomposeMeasureScopeImpl<'scope>, Constraints) -> MeasureResult;
347
348pub struct SubcomposeLayoutNode {
350 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
351 parent: Cell<Option<NodeId>>,
353 id: Cell<Option<NodeId>>,
355 needs_measure: Cell<bool>,
357 needs_layout: Cell<bool>,
358 needs_semantics: Cell<bool>,
359 needs_redraw: Cell<bool>,
360 needs_pointer_pass: Cell<bool>,
361 needs_focus_sync: Cell<bool>,
362 virtual_children_count: Cell<usize>,
363}
364
365impl SubcomposeLayoutNode {
366 pub fn new(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
367 let inner = Rc::new(RefCell::new(SubcomposeLayoutNodeInner::new(measure_policy)));
368 let node = Self {
369 inner,
370 parent: Cell::new(None),
371 id: Cell::new(None),
372 needs_measure: Cell::new(true),
373 needs_layout: Cell::new(true),
374 needs_semantics: Cell::new(true),
375 needs_redraw: Cell::new(true),
376 needs_pointer_pass: Cell::new(false),
377 needs_focus_sync: Cell::new(false),
378 virtual_children_count: Cell::new(0),
379 };
380 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
383 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
384 node
385 }
386
387 pub fn with_content_type_policy(modifier: Modifier, measure_policy: Rc<MeasurePolicy>) -> Self {
393 let mut inner_data = SubcomposeLayoutNodeInner::new(measure_policy);
394 inner_data
395 .state
396 .set_policy(Box::new(cranpose_core::ContentTypeReusePolicy::new()));
397 let inner = Rc::new(RefCell::new(inner_data));
398 let node = Self {
399 inner,
400 parent: Cell::new(None),
401 id: Cell::new(None),
402 needs_measure: Cell::new(true),
403 needs_layout: Cell::new(true),
404 needs_semantics: Cell::new(true),
405 needs_redraw: Cell::new(true),
406 needs_pointer_pass: Cell::new(false),
407 needs_focus_sync: Cell::new(false),
408 virtual_children_count: Cell::new(0),
409 };
410 let (invalidations, _) = node.inner.borrow_mut().set_modifier_collect(modifier);
413 node.dispatch_modifier_invalidations(&invalidations, NodeCapabilities::empty());
414 node
415 }
416
417 pub fn handle(&self) -> SubcomposeLayoutNodeHandle {
418 SubcomposeLayoutNodeHandle {
419 inner: Rc::clone(&self.inner),
420 }
421 }
422
423 pub fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
424 self.inner.borrow_mut().set_measure_policy(policy);
425 }
426
427 pub fn set_modifier(&mut self, modifier: Modifier) {
428 let prev_caps = self.modifier_capabilities();
430 let (invalidations, modifier_changed) = {
432 let mut inner = self.inner.borrow_mut();
433 inner.set_modifier_collect(modifier)
434 };
435 self.dispatch_modifier_invalidations(&invalidations, prev_caps);
438 if modifier_changed {
439 self.mark_needs_measure();
440 self.request_semantics_update();
441 }
442 }
443
444 pub fn set_debug_modifiers(&mut self, enabled: bool) {
445 self.inner.borrow_mut().set_debug_modifiers(enabled);
446 }
447
448 pub fn modifier(&self) -> Modifier {
449 self.handle().modifier()
450 }
451
452 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
453 self.inner.borrow().resolved_modifiers
454 }
455
456 pub fn state(&self) -> Ref<'_, SubcomposeState> {
457 Ref::map(self.inner.borrow(), |inner| &inner.state)
458 }
459
460 pub fn state_mut(&self) -> RefMut<'_, SubcomposeState> {
461 RefMut::map(self.inner.borrow_mut(), |inner| &mut inner.state)
462 }
463
464 pub fn active_children(&self) -> Vec<NodeId> {
465 self.inner.borrow().children.iter().copied().collect()
466 }
467
468 pub fn mark_needs_measure(&self) {
470 self.needs_measure.set(true);
471 self.needs_layout.set(true);
472 }
473
474 pub fn mark_needs_layout_flag(&self) {
476 self.needs_layout.set(true);
477 }
478
479 pub fn mark_needs_redraw(&self) {
481 self.needs_redraw.set(true);
482 if let Some(id) = self.id.get() {
483 crate::schedule_draw_repass(id);
484 }
485 crate::request_render_invalidation();
486 }
487
488 pub fn needs_measure(&self) -> bool {
490 self.needs_measure.get()
491 }
492
493 pub fn mark_needs_semantics(&self) {
495 self.needs_semantics.set(true);
496 }
497
498 pub fn needs_semantics_flag(&self) -> bool {
500 self.needs_semantics.get()
501 }
502
503 pub fn needs_redraw(&self) -> bool {
505 self.needs_redraw.get()
506 }
507
508 pub fn clear_needs_redraw(&self) {
509 self.needs_redraw.set(false);
510 }
511
512 pub fn mark_needs_pointer_pass(&self) {
514 self.needs_pointer_pass.set(true);
515 }
516
517 pub fn needs_pointer_pass(&self) -> bool {
519 self.needs_pointer_pass.get()
520 }
521
522 pub fn clear_needs_pointer_pass(&self) {
524 self.needs_pointer_pass.set(false);
525 }
526
527 pub fn mark_needs_focus_sync(&self) {
529 self.needs_focus_sync.set(true);
530 }
531
532 pub fn needs_focus_sync(&self) -> bool {
534 self.needs_focus_sync.get()
535 }
536
537 pub fn clear_needs_focus_sync(&self) {
539 self.needs_focus_sync.set(false);
540 }
541
542 fn request_semantics_update(&self) {
543 let already_dirty = self.needs_semantics.replace(true);
544 if already_dirty {
545 return;
546 }
547
548 if let Some(id) = self.id.get() {
549 cranpose_core::queue_semantics_invalidation(id);
550 }
551 }
552
553 pub fn modifier_capabilities(&self) -> NodeCapabilities {
555 self.inner.borrow().modifier_capabilities
556 }
557
558 pub fn has_layout_modifier_nodes(&self) -> bool {
559 self.modifier_capabilities()
560 .contains(NodeCapabilities::LAYOUT)
561 }
562
563 pub fn has_draw_modifier_nodes(&self) -> bool {
564 self.modifier_capabilities()
565 .contains(NodeCapabilities::DRAW)
566 }
567
568 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
569 self.modifier_capabilities()
570 .contains(NodeCapabilities::POINTER_INPUT)
571 }
572
573 pub fn has_semantics_modifier_nodes(&self) -> bool {
574 self.modifier_capabilities()
575 .contains(NodeCapabilities::SEMANTICS)
576 }
577
578 pub fn has_focus_modifier_nodes(&self) -> bool {
579 self.modifier_capabilities()
580 .contains(NodeCapabilities::FOCUS)
581 }
582
583 fn dispatch_modifier_invalidations(
590 &self,
591 invalidations: &[ModifierInvalidation],
592 prev_caps: NodeCapabilities,
593 ) {
594 let curr_caps = self.modifier_capabilities();
595 for invalidation in invalidations {
596 match invalidation.kind() {
597 InvalidationKind::Layout => {
598 if curr_caps.contains(NodeCapabilities::LAYOUT)
599 || prev_caps.contains(NodeCapabilities::LAYOUT)
600 {
601 self.mark_needs_measure();
602 }
603 }
604 InvalidationKind::Draw => {
605 if curr_caps.contains(NodeCapabilities::DRAW)
606 || prev_caps.contains(NodeCapabilities::DRAW)
607 {
608 self.mark_needs_redraw();
609 }
610 }
611 InvalidationKind::PointerInput => {
612 if curr_caps.contains(NodeCapabilities::POINTER_INPUT)
613 || prev_caps.contains(NodeCapabilities::POINTER_INPUT)
614 {
615 self.mark_needs_pointer_pass();
616 crate::request_pointer_invalidation();
617 if let Some(id) = self.id.get() {
619 crate::schedule_pointer_repass(id);
620 }
621 }
622 }
623 InvalidationKind::Semantics => {
624 self.request_semantics_update();
625 }
626 InvalidationKind::Focus => {
627 if curr_caps.contains(NodeCapabilities::FOCUS)
628 || prev_caps.contains(NodeCapabilities::FOCUS)
629 {
630 self.mark_needs_focus_sync();
631 crate::request_focus_invalidation();
632 if let Some(id) = self.id.get() {
634 crate::schedule_focus_invalidation(id);
635 }
636 }
637 }
638 }
639 }
640 }
641}
642
643impl cranpose_core::Node for SubcomposeLayoutNode {
644 fn mount(&mut self) {
645 let mut inner = self.inner.borrow_mut();
646 let (chain, mut context) = inner.modifier_chain.chain_and_context_mut();
647 chain.repair_chain();
648 chain.attach_nodes(&mut *context);
649 }
650
651 fn unmount(&mut self) {
652 self.inner
653 .borrow_mut()
654 .modifier_chain
655 .chain_mut()
656 .detach_nodes();
657 }
658
659 fn insert_child(&mut self, child: NodeId) {
660 if is_virtual_node(child) {
661 let count = self.virtual_children_count.get();
662 self.virtual_children_count.set(count + 1);
663 }
664 self.inner.borrow_mut().children.insert(child);
665 }
666
667 fn remove_child(&mut self, child: NodeId) {
668 if self.inner.borrow_mut().children.shift_remove(&child) && is_virtual_node(child) {
669 let count = self.virtual_children_count.get();
670 if count > 0 {
671 self.virtual_children_count.set(count - 1);
672 }
673 }
674 }
675
676 fn move_child(&mut self, from: usize, to: usize) {
677 let mut inner = self.inner.borrow_mut();
678 if from == to || from >= inner.children.len() {
679 return;
680 }
681 let mut ordered: Vec<NodeId> = inner.children.iter().copied().collect();
682 let child = ordered.remove(from);
683 let target = to.min(ordered.len());
684 ordered.insert(target, child);
685 inner.children.clear();
686 for id in ordered {
687 inner.children.insert(id);
688 }
689 }
690
691 fn update_children(&mut self, children: &[NodeId]) {
692 let mut inner = self.inner.borrow_mut();
693 inner.children.clear();
694 for &child in children {
695 inner.children.insert(child);
696 }
697 }
698
699 fn children(&self) -> Vec<NodeId> {
700 let inner = self.inner.borrow();
701 if !inner.last_placements.is_empty() {
704 inner.last_placements.clone()
705 } else {
706 inner.children.iter().copied().collect()
707 }
708 }
709
710 fn set_node_id(&mut self, id: NodeId) {
711 self.id.set(Some(id));
712 self.inner.borrow_mut().modifier_chain.set_node_id(Some(id));
713 }
714
715 fn on_attached_to_parent(&mut self, parent: NodeId) {
716 self.parent.set(Some(parent));
717 }
718
719 fn on_removed_from_parent(&mut self) {
720 self.parent.set(None);
721 }
722
723 fn parent(&self) -> Option<NodeId> {
724 self.parent.get()
725 }
726
727 fn mark_needs_layout(&self) {
728 self.needs_layout.set(true);
729 }
730
731 fn needs_layout(&self) -> bool {
732 self.needs_layout.get()
733 }
734
735 fn mark_needs_measure(&self) {
736 self.needs_measure.set(true);
737 self.needs_layout.set(true); }
739
740 fn needs_measure(&self) -> bool {
741 self.needs_measure.get()
742 }
743
744 fn mark_needs_semantics(&self) {
745 self.needs_semantics.set(true);
746 }
747
748 fn needs_semantics(&self) -> bool {
749 self.needs_semantics.get()
750 }
751
752 fn set_parent_for_bubbling(&mut self, parent: NodeId) {
754 self.parent.set(Some(parent));
755 }
756}
757
758#[derive(Clone)]
759pub struct SubcomposeLayoutNodeHandle {
760 inner: Rc<RefCell<SubcomposeLayoutNodeInner>>,
761}
762
763impl SubcomposeLayoutNodeHandle {
764 pub fn modifier(&self) -> Modifier {
765 self.inner.borrow().modifier.clone()
766 }
767
768 pub fn layout_properties(&self) -> crate::modifier::LayoutProperties {
769 self.resolved_modifiers().layout_properties()
770 }
771
772 pub fn resolved_modifiers(&self) -> ResolvedModifiers {
773 self.inner.borrow().resolved_modifiers
774 }
775
776 pub fn total_offset(&self) -> Point {
777 self.resolved_modifiers().offset()
778 }
779
780 pub fn modifier_capabilities(&self) -> NodeCapabilities {
781 self.inner.borrow().modifier_capabilities
782 }
783
784 pub fn has_layout_modifier_nodes(&self) -> bool {
785 self.modifier_capabilities()
786 .contains(NodeCapabilities::LAYOUT)
787 }
788
789 pub fn has_draw_modifier_nodes(&self) -> bool {
790 self.modifier_capabilities()
791 .contains(NodeCapabilities::DRAW)
792 }
793
794 pub fn has_pointer_input_modifier_nodes(&self) -> bool {
795 self.modifier_capabilities()
796 .contains(NodeCapabilities::POINTER_INPUT)
797 }
798
799 pub fn has_semantics_modifier_nodes(&self) -> bool {
800 self.modifier_capabilities()
801 .contains(NodeCapabilities::SEMANTICS)
802 }
803
804 pub fn has_focus_modifier_nodes(&self) -> bool {
805 self.modifier_capabilities()
806 .contains(NodeCapabilities::FOCUS)
807 }
808
809 pub fn set_debug_modifiers(&self, enabled: bool) {
810 self.inner.borrow_mut().set_debug_modifiers(enabled);
811 }
812
813 pub fn measure<'a>(
814 &self,
815 composer: &Composer,
816 node_id: NodeId,
817 constraints: Constraints,
818 measurer: Box<dyn FnMut(NodeId, Constraints) -> Size + 'a>,
819 error: Rc<RefCell<Option<NodeError>>>,
820 ) -> Result<MeasureResult, NodeError> {
821 let (policy, mut state, slots) = {
822 let mut inner = self.inner.borrow_mut();
823 let policy = Rc::clone(&inner.measure_policy);
824 let state = std::mem::take(&mut inner.state);
825 let slots = std::mem::take(&mut inner.slots);
826 (policy, state, slots)
827 };
828 state.begin_pass();
829
830 let previous = composer.phase();
831 if !matches!(previous, Phase::Measure | Phase::Layout) {
832 composer.enter_phase(Phase::Measure);
833 }
834
835 let slots_host = Rc::new(SlotsHost::new(slots));
836 let constraints_copy = constraints;
837 let result = composer.subcompose_slot(&slots_host, Some(node_id), |inner_composer| {
846 let mut scope = SubcomposeMeasureScopeImpl::new(
847 inner_composer.clone(),
848 &mut state,
849 constraints_copy,
850 measurer,
851 Rc::clone(&error),
852 self.clone(), node_id, );
855 (policy)(&mut scope, constraints_copy)
856 })?;
857
858 state.finish_pass();
859
860 if previous != composer.phase() {
861 composer.enter_phase(previous);
862 }
863
864 {
865 let mut inner = self.inner.borrow_mut();
866 inner.slots = slots_host.take();
867 inner.state = state;
868
869 inner.last_placements = result.placements.iter().map(|p| p.node_id).collect();
874 }
875
876 Ok(result)
877 }
878
879 pub fn set_active_children<I>(&self, children: I)
880 where
881 I: IntoIterator<Item = NodeId>,
882 {
883 let mut inner = self.inner.borrow_mut();
884 inner.children.clear();
885 for child in children {
886 inner.children.insert(child);
887 }
888 }
889}
890
891struct SubcomposeLayoutNodeInner {
892 modifier: Modifier,
893 modifier_chain: ModifierChainHandle,
894 resolved_modifiers: ResolvedModifiers,
895 modifier_capabilities: NodeCapabilities,
896 state: SubcomposeState,
897 measure_policy: Rc<MeasurePolicy>,
898 children: IndexSet<NodeId>,
899 slots: SlotBackend,
900 debug_modifiers: bool,
901 virtual_nodes: HashMap<NodeId, Rc<LayoutNode>>,
903 last_placements: Vec<NodeId>,
906}
907
908impl SubcomposeLayoutNodeInner {
909 fn new(measure_policy: Rc<MeasurePolicy>) -> Self {
910 Self {
911 modifier: Modifier::empty(),
912 modifier_chain: ModifierChainHandle::new(),
913 resolved_modifiers: ResolvedModifiers::default(),
914 modifier_capabilities: NodeCapabilities::default(),
915 state: SubcomposeState::default(),
916 measure_policy,
917 children: IndexSet::new(),
918 slots: SlotBackend::default(),
919 debug_modifiers: false,
920 virtual_nodes: HashMap::new(),
921 last_placements: Vec::new(),
922 }
923 }
924
925 fn set_measure_policy(&mut self, policy: Rc<MeasurePolicy>) {
926 self.measure_policy = policy;
927 }
928
929 fn set_modifier_collect(&mut self, modifier: Modifier) -> (Vec<ModifierInvalidation>, bool) {
932 let modifier_changed = self.modifier != modifier;
933 self.modifier = modifier;
934 self.modifier_chain.set_debug_logging(self.debug_modifiers);
935 let modifier_local_invalidations = self.modifier_chain.update(&self.modifier);
936 self.resolved_modifiers = self.modifier_chain.resolved_modifiers();
937 self.modifier_capabilities = self.modifier_chain.capabilities();
938
939 let mut invalidations = self.modifier_chain.take_invalidations();
941 invalidations.extend(modifier_local_invalidations);
942
943 (invalidations, modifier_changed)
944 }
945
946 fn set_debug_modifiers(&mut self, enabled: bool) {
947 self.debug_modifiers = enabled;
948 self.modifier_chain.set_debug_logging(enabled);
949 }
950}
951
952#[cfg(test)]
953#[path = "tests/subcompose_layout_tests.rs"]
954mod tests;