layer_shika_domain/entities/
output_registry.rs1use 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}