layer_shika_domain/entities/
output_registry.rs

1use crate::value_objects::output_handle::OutputHandle;
2use crate::value_objects::output_info::OutputInfo;
3use crate::value_objects::output_policy::OutputPolicy;
4use std::collections::HashMap;
5
6#[derive(Clone)]
7pub struct OutputRegistry {
8    outputs: HashMap<OutputHandle, OutputInfo>,
9    primary_output: Option<OutputHandle>,
10    active_output: Option<OutputHandle>,
11}
12
13impl OutputRegistry {
14    pub fn new() -> Self {
15        Self {
16            outputs: HashMap::new(),
17            primary_output: None,
18            active_output: None,
19        }
20    }
21
22    pub fn add(&mut self, info: OutputInfo) -> OutputHandle {
23        let handle = info.handle();
24        let is_first = self.outputs.is_empty();
25
26        self.outputs.insert(handle, info);
27
28        if is_first {
29            self.primary_output = Some(handle);
30        }
31
32        handle
33    }
34
35    pub fn remove(&mut self, handle: OutputHandle) -> Option<OutputInfo> {
36        let info = self.outputs.remove(&handle);
37
38        if self.primary_output == Some(handle) {
39            self.primary_output = self.outputs.keys().next().copied();
40        }
41
42        if self.active_output == Some(handle) {
43            self.active_output = None;
44        }
45
46        info
47    }
48
49    pub fn get(&self, handle: OutputHandle) -> Option<&OutputInfo> {
50        self.outputs.get(&handle)
51    }
52
53    pub fn get_mut(&mut self, handle: OutputHandle) -> Option<&mut OutputInfo> {
54        self.outputs.get_mut(&handle)
55    }
56
57    pub fn find_by_name(&self, name: &str) -> Option<(OutputHandle, &OutputInfo)> {
58        self.outputs
59            .iter()
60            .find(|(_, info)| info.name() == Some(name))
61            .map(|(handle, info)| (*handle, info))
62    }
63
64    pub fn find_by_model(&self, model: &str) -> Option<(OutputHandle, &OutputInfo)> {
65        self.outputs
66            .iter()
67            .find(|(_, info)| info.geometry().and_then(|g| g.model.as_deref()) == Some(model))
68            .map(|(handle, info)| (*handle, info))
69    }
70
71    pub fn all(&self) -> impl Iterator<Item = (OutputHandle, &OutputInfo)> {
72        self.outputs.iter().map(|(handle, info)| (*handle, info))
73    }
74
75    pub fn all_info(&self) -> impl Iterator<Item = &OutputInfo> {
76        self.outputs.values()
77    }
78
79    pub fn primary(&self) -> Option<(OutputHandle, &OutputInfo)> {
80        self.primary_output
81            .and_then(|handle| self.outputs.get(&handle).map(|info| (handle, info)))
82    }
83
84    pub fn primary_handle(&self) -> Option<OutputHandle> {
85        self.primary_output
86    }
87
88    pub fn active(&self) -> Option<(OutputHandle, &OutputInfo)> {
89        self.active_output
90            .and_then(|handle| self.outputs.get(&handle).map(|info| (handle, info)))
91    }
92
93    pub fn active_handle(&self) -> Option<OutputHandle> {
94        self.active_output
95    }
96
97    pub fn active_or_primary(&self) -> Option<(OutputHandle, &OutputInfo)> {
98        self.active().or_else(|| self.primary())
99    }
100
101    pub fn active_or_primary_handle(&self) -> Option<OutputHandle> {
102        self.active_output.or(self.primary_output)
103    }
104
105    pub fn set_active(&mut self, handle: Option<OutputHandle>) {
106        if let Some(h) = handle {
107            if self.outputs.contains_key(&h) {
108                self.active_output = Some(h);
109            }
110        } else {
111            self.active_output = None;
112        }
113    }
114
115    pub fn set_primary(&mut self, handle: OutputHandle) -> bool {
116        if !self.outputs.contains_key(&handle) {
117            return false;
118        }
119
120        if let Some(old_primary) = self.primary_output {
121            if let Some(old_info) = self.outputs.get_mut(&old_primary) {
122                old_info.set_primary(false);
123            }
124        }
125
126        self.primary_output = Some(handle);
127
128        if let Some(new_info) = self.outputs.get_mut(&handle) {
129            new_info.set_primary(true);
130        }
131
132        true
133    }
134
135    pub fn select_by_policy(&self, policy: &OutputPolicy) -> Vec<(OutputHandle, &OutputInfo)> {
136        self.outputs
137            .iter()
138            .filter(|(_, info)| policy.should_render(info))
139            .map(|(handle, info)| (*handle, info))
140            .collect()
141    }
142
143    pub fn count(&self) -> usize {
144        self.outputs.len()
145    }
146
147    pub fn is_empty(&self) -> bool {
148        self.outputs.is_empty()
149    }
150}
151
152impl Default for OutputRegistry {
153    fn default() -> Self {
154        Self::new()
155    }
156}