polyhorn_ios/raw/
compositor.rs1use dispatch::Queue;
2use polyhorn_core::{Command, Composition};
3use polyhorn_ui::layout::LayoutTree;
4use std::sync::atomic::{AtomicUsize, Ordering};
5use std::sync::{Arc, RwLock};
6
7use super::{Environment, OpaqueContainer, Platform, QueueBound};
8
9#[derive(Clone)]
13pub struct Compositor {
14 buffer: Arc<QueueBound<Composition<Platform>>>,
15 counter: Arc<AtomicUsize>,
16 layout_tree: Arc<RwLock<LayoutTree>>,
17}
18
19impl Compositor {
20 pub fn new(layout_tree: Arc<RwLock<LayoutTree>>) -> Compositor {
22 Compositor {
23 buffer: Arc::new(QueueBound::new(Queue::main(), || Default::default())),
24 counter: Arc::new(AtomicUsize::default()),
25 layout_tree,
26 }
27 }
28
29 fn next_id(&mut self) -> ContainerID {
30 let id = self.counter.fetch_add(1, Ordering::Relaxed);
31 ContainerID(id)
32 }
33
34 pub(crate) fn track(&mut self, container: OpaqueContainer) -> ContainerID {
35 let id = self.next_id();
36
37 unsafe {
38 self.buffer.with_adopt(container, move |state, container| {
39 state.insert(id, container);
40 });
41 }
42
43 id
44 }
45}
46
47impl polyhorn_core::Compositor<Platform> for Compositor {
48 fn buffer(&self) -> CommandBuffer {
49 CommandBuffer {
50 compositor: self.clone(),
51 commands: vec![],
52 }
53 }
54}
55
56#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
58pub struct ContainerID(usize);
59
60pub struct CommandBuffer {
63 compositor: Compositor,
64 commands: Vec<Command<Platform>>,
65}
66
67impl polyhorn_core::CommandBuffer<Platform> for CommandBuffer {
68 fn mount<F>(&mut self, parent_id: ContainerID, initializer: F) -> ContainerID
69 where
70 F: FnOnce(&mut OpaqueContainer, &mut Environment) -> OpaqueContainer + Send + 'static,
71 {
72 let id = self.compositor.next_id();
73 self.commands
74 .push(Command::Mount(id, parent_id, Box::new(initializer)));
75 id
76 }
77
78 fn mutate<F>(&mut self, ids: &[ContainerID], mutator: F)
79 where
80 F: FnOnce(&mut [&mut OpaqueContainer], &mut Environment) + Send + 'static,
81 {
82 self.commands
83 .push(Command::Mutate(ids.to_owned(), Box::new(mutator)));
84 }
85
86 fn unmount(&mut self, id: ContainerID) {
87 self.commands.push(Command::Unmount(id));
88 }
89
90 fn layout(&mut self) {
91 self.mutate(&[], |_, environment| {
92 let mut layout_tree = environment.layout_tree().write().unwrap();
93 layout_tree.recompute_roots();
94 });
95 }
96
97 fn commit(mut self) {
98 let commands = std::mem::take(&mut self.commands);
99
100 let layout_tree = self.compositor.layout_tree.clone();
101
102 self.compositor.buffer.with(move |state| {
103 let mut environment = Environment::new(layout_tree.clone());
105 for command in commands {
106 state.process(&mut environment, command);
107 }
108 });
109 }
110}