orbital_base_components/collection/state/
expansion.rs1use 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}