1use std::{
2 path::{Path, PathBuf},
3 time::SystemTime,
4};
5
6use crate::{StyleLoadError, Stylesheet};
7
8#[derive(Clone, Debug)]
10pub struct LoadedStyle {
11 modified: SystemTime,
12 path: PathBuf,
13 style: Stylesheet,
14}
15
16impl LoadedStyle {
17 pub fn load(path: impl AsRef<Path>) -> Result<Self, StyleLoadError> {
19 let modified = path.as_ref().metadata()?.modified()?;
20 let style = Stylesheet::load(&path)?;
21 Ok(Self {
22 modified,
23 path: path.as_ref().to_path_buf(),
24 style,
25 })
26 }
27
28 pub fn reload(&mut self) -> Result<bool, StyleLoadError> {
32 let modified = self.path.metadata()?.modified()?;
33
34 let needs_reload = modified > self.modified;
35 if needs_reload {
36 self.modified = modified;
37 self.style = Stylesheet::load(&self.path)?;
38 }
39
40 Ok(needs_reload)
41 }
42}
43
44#[derive(Clone, Debug)]
46pub enum LoadedStyleKind {
47 Loaded(LoadedStyle),
48 Inline(Stylesheet),
49}
50
51impl LoadedStyleKind {
52 pub fn reload(&mut self) -> Result<bool, StyleLoadError> {
56 match self {
57 Self::Loaded(loaded) => loaded.reload(),
58 Self::Inline(_) => Ok(false),
59 }
60 }
61
62 pub fn style(&self) -> &Stylesheet {
64 match self {
65 Self::Loaded(style) => &style.style,
66 Self::Inline(style) => style,
67 }
68 }
69}
70
71impl From<Stylesheet> for LoadedStyleKind {
72 fn from(style: Stylesheet) -> Self {
73 Self::Inline(style)
74 }
75}
76
77impl TryFrom<&str> for LoadedStyleKind {
78 type Error = StyleLoadError;
79
80 fn try_from(path: &str) -> Result<Self, Self::Error> {
81 Ok(Self::Loaded(LoadedStyle::load(path)?))
82 }
83}
84
85impl TryFrom<&Path> for LoadedStyleKind {
86 type Error = StyleLoadError;
87
88 fn try_from(path: &Path) -> Result<Self, Self::Error> {
89 Ok(Self::Loaded(LoadedStyle::load(path)?))
90 }
91}
92
93#[derive(Clone, Debug)]
97pub struct StyleLoader {
98 styles: Vec<LoadedStyleKind>,
99 cache: Stylesheet,
100}
101
102impl StyleLoader {
103 pub fn new() -> Self {
105 Self {
106 styles: Vec::new(),
107 cache: Stylesheet::new(),
108 }
109 }
110
111 pub fn clear(&mut self) {
112 self.styles.clear();
113 self.cache = Stylesheet::new();
114 }
115
116 pub fn add_style<T: TryInto<LoadedStyleKind>>(&mut self, style: T) -> Result<(), T::Error> {
118 self.styles.push(style.try_into()?);
119 self.compute_cache();
120 Ok(())
121 }
122
123 fn compute_cache(&mut self) {
125 self.cache = Stylesheet::new();
126
127 for style in self.styles.iter() {
128 self.cache.extend(style.style().clone());
129 }
130 }
131
132 pub fn reload(&mut self) -> Result<bool, StyleLoadError> {
134 let mut needs_reload = false;
135
136 for style in self.styles.iter_mut() {
137 if style.reload()? {
138 needs_reload = true;
139 }
140 }
141
142 if needs_reload {
143 self.compute_cache();
144 }
145
146 Ok(needs_reload)
147 }
148
149 pub fn style(&self) -> &Stylesheet {
151 &self.cache
152 }
153}