Skip to main content

orbital_base_components/collection/state/
expansion.rs

1use std::collections::HashSet;
2
3use crate::signals::SignalModel;
4use crate::Handler;
5
6#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
7pub enum ExpansionTrigger {
8    #[default]
9    Row,
10    IconContainer,
11}
12
13#[derive(Clone)]
14pub struct CollectionExpansionState {
15    pub open_items: SignalModel<HashSet<String>>,
16    pub default_open: Vec<String>,
17    pub expansion_trigger: ExpansionTrigger,
18    pub on_expansion_toggle: Option<Handler<(String, bool)>>,
19}
20
21impl CollectionExpansionState {
22    pub fn new(open_items: SignalModel<HashSet<String>>) -> Self {
23        Self {
24            open_items,
25            default_open: Vec::new(),
26            expansion_trigger: ExpansionTrigger::default(),
27            on_expansion_toggle: None,
28        }
29    }
30
31    pub fn with_default_open(mut self, default_open: Vec<String>) -> Self {
32        if self.open_items.get().is_empty() && !default_open.is_empty() {
33            self.open_items
34                .update(|open| open.extend(default_open.iter().cloned()));
35        }
36        self.default_open = default_open;
37        self
38    }
39
40    pub fn with_expansion_trigger(mut self, trigger: ExpansionTrigger) -> Self {
41        self.expansion_trigger = trigger;
42        self
43    }
44
45    pub fn with_on_expansion_toggle(mut self, handler: Handler<(String, bool)>) -> Self {
46        self.on_expansion_toggle = Some(handler);
47        self
48    }
49
50    pub fn is_open(&self, item_id: &str) -> bool {
51        self.open_items.with(|open| open.contains(item_id))
52    }
53
54    pub fn toggle(&self, item_id: String, is_branch: bool) {
55        if !is_branch {
56            return;
57        }
58        let was_open = self.is_open(&item_id);
59        self.open_items.update(|open| {
60            if was_open {
61                open.remove(&item_id);
62            } else {
63                open.insert(item_id.clone());
64            }
65        });
66        if let Some(handler) = &self.on_expansion_toggle {
67            handler.run((item_id, !was_open));
68        }
69    }
70
71    pub fn set_expansion(&self, item_id: String, expanded: bool) {
72        self.open_items.update(|open| {
73            if expanded {
74                open.insert(item_id.clone());
75            } else {
76                open.remove(&item_id);
77            }
78        });
79        if let Some(handler) = &self.on_expansion_toggle {
80            handler.run((item_id, expanded));
81        }
82    }
83}