Skip to main content

polyhorn_ios/handles/
view.rs

1use polyhorn_core::{CommandBuffer as _, Compositor as _};
2use polyhorn_ui::geometry::Size;
3
4use crate::raw::{Animator, CommandBuffer, Compositor, ContainerID};
5use crate::WeakReference;
6
7/// Platform-specific implementation of the view handle trait that can be used
8/// to execute imperative code against a view.
9pub struct ViewHandle {
10    pub(crate) container_id: WeakReference<Option<ContainerID>>,
11    pub(crate) compositor: Compositor,
12}
13
14impl polyhorn_ui::handles::ViewHandle for ViewHandle {
15    fn layout_guide(&self) -> polyhorn_ui::layout::LayoutGuide<f32> {
16        unimplemented!("Help")
17    }
18
19    fn size<F>(&self, callback: F)
20    where
21        F: FnOnce(Size<f32>) + Send + 'static,
22    {
23        let mut buffer = self.compositor.buffer();
24        self.size_with_buffer(&mut buffer, callback);
25        buffer.commit();
26    }
27
28    fn size_with_buffer<F>(&self, buffer: &mut CommandBuffer, callback: F)
29    where
30        F: FnOnce(Size<f32>) + Send + 'static,
31    {
32        let id = match self.container_id.apply(|&mut id| id).flatten() {
33            Some(id) => id,
34            None => return,
35        };
36
37        buffer.mutate(&[id], move |containers, _| {
38            let container = &mut containers[0];
39
40            if let Some(layout) = container.layout() {
41                callback(layout.current().size);
42            }
43        });
44    }
45}
46
47impl polyhorn_ui::animation::Animatable for ViewHandle {
48    type Animator = Animator;
49    type CommandBuffer = CommandBuffer;
50
51    fn animate<F>(&mut self, animations: F)
52    where
53        F: FnOnce(&mut Animator) + Send + 'static,
54    {
55        // Create a new command buffer.
56        let mut buffer = self.compositor.buffer();
57
58        self.animate_with_buffer(&mut buffer, animations);
59
60        // And finally, commit the command buffer to synchronize the mutation.
61        buffer.commit();
62    }
63
64    fn animate_with_buffer<F>(&mut self, buffer: &mut CommandBuffer, animations: F)
65    where
66        F: FnOnce(&mut Animator) + Send + 'static,
67    {
68        let container_id = match self.container_id.apply(|id| id.to_owned()).flatten() {
69            Some(container_id) => container_id,
70            None => panic!("Can't animate view that has not yet been mounted."),
71        };
72
73        // Add a mutation of the container to the command buffer.
74        buffer.mutate(&[container_id], |containers, _| {
75            if let Some(view) = containers[0].container().to_view() {
76                animations(&mut Animator::new(view));
77            }
78        });
79    }
80}