gpui_ce_motion/
presence.rs1use crate::AnimationError;
3
4#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
6pub enum PresenceMode {
7 #[default]
9 Sync,
10 Wait,
12}
13
14#[derive(Clone, Debug)]
16pub struct PresenceChild<K> {
17 key: K,
18 present: bool,
19}
20
21impl<K> PresenceChild<K> {
22 pub fn key(&self) -> &K {
24 &self.key
25 }
26
27 pub fn is_present(&self) -> bool {
29 self.present
30 }
31}
32
33#[derive(Debug)]
36pub struct PresenceGroup<K> {
37 children: Vec<PresenceChild<K>>,
38 pending: Vec<K>,
39 mode: PresenceMode,
40}
41
42impl<K: Clone + PartialEq> PresenceGroup<K> {
43 pub fn new(mode: PresenceMode) -> Self {
45 Self {
46 children: Vec::new(),
47 pending: Vec::new(),
48 mode,
49 }
50 }
51
52 pub fn update(&mut self, keys: impl IntoIterator<Item = K>) -> Result<(), AnimationError> {
55 let keys: Vec<_> = keys.into_iter().collect();
56
57 if keys.iter().enumerate().any(|(i, k)| keys[..i].contains(k)) {
58 return Err(AnimationError::Index);
59 }
60
61 for child in &mut self.children {
62 child.present = keys.contains(&child.key);
63 }
64
65 let waiting = self.mode == PresenceMode::Wait && self.children.iter().any(|c| !c.present);
66
67 self.pending.clear();
68
69 for key in keys {
70 if self.children.iter().any(|c| c.key == key) {
71 continue;
72 }
73
74 if waiting {
75 self.pending.push(key);
76 } else {
77 self.children.push(PresenceChild { key, present: true });
78 }
79 }
80
81 Ok(())
82 }
83
84 pub fn children(&self) -> &[PresenceChild<K>] {
86 &self.children
87 }
88
89 pub fn finish_exit(&mut self, key: &K) -> bool {
92 let Some(ix) = self
93 .children
94 .iter()
95 .position(|c| &c.key == key && !c.present)
96 else {
97 return false;
98 };
99
100 self.children.remove(ix);
101
102 if self.children.iter().all(|c| c.present) {
103 self.children.extend(
104 self.pending
105 .drain(..)
106 .map(|key| PresenceChild { key, present: true }),
107 );
108 }
109
110 true
111 }
112}