1use crate::Widget;
2use crate::erased::{Constructor, construct};
3
4#[derive(Default, Clone)]
7pub struct Registry {
8 widgets: Vec<(&'static str, Constructor)>,
9}
10
11impl Registry {
12 pub fn new() -> Self {
13 Self::default()
14 }
15
16 pub fn widget<W: Widget>(&mut self, name: &'static str) {
18 self.widgets.push((name, construct::<W>));
19 }
20
21 #[doc(hidden)]
22 pub fn get(&self, name: &str) -> Option<Constructor> {
23 self.widgets
24 .iter()
25 .find(|(registered, _)| *registered == name)
26 .map(|(_, constructor)| *constructor)
27 }
28
29 #[doc(hidden)]
32 pub fn duplicates(&self) -> Vec<&'static str> {
33 let mut names: Vec<_> = self.widgets.iter().map(|(name, _)| *name).collect();
34 names.sort_unstable();
35 let mut duplicates: Vec<_> = names
36 .windows(2)
37 .filter(|pair| pair[0] == pair[1])
38 .map(|pair| pair[0])
39 .collect();
40 duplicates.dedup();
41 duplicates
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use crate::ui::{Item, label};
49 use crate::{Effect, Task};
50
51 struct Dummy;
52
53 impl Widget for Dummy {
54 type Config = toml::Table;
55 type Message = ();
56
57 fn new(_: Self::Config) -> (Self, Task<()>) {
58 (Self, Task::none())
59 }
60
61 fn update(&mut self, _: ()) -> Effect<()> {
62 Effect::none()
63 }
64
65 fn item(&self) -> Item<()> {
66 Item::new(label("dummy"))
67 }
68 }
69
70 #[test]
71 fn finds_and_reports_duplicates() {
72 let mut registry = Registry::new();
73 registry.widget::<Dummy>("a");
74 registry.widget::<Dummy>("b");
75 registry.widget::<Dummy>("a");
76 assert!(registry.get("b").is_some());
77 assert!(registry.get("c").is_none());
78 assert_eq!(registry.duplicates(), ["a"]);
79 }
80}