fyrox_ui/style/
resource.rs1use crate::style::{IntoPrimitive, Style, StyleProperty, StyledProperty};
24use fyrox_core::{
25 io::FileLoadError,
26 log::Log,
27 type_traits::prelude::*,
28 visitor::{prelude::*, VisitError, Visitor},
29 ImmutableString, Uuid,
30};
31use fyrox_resource::{
32 io::ResourceIo,
33 loader::{BoxedLoaderFuture, LoaderPayload, ResourceLoader},
34 manager::ResourceManager,
35 state::LoadError,
36 Resource, ResourceData,
37};
38use std::{
39 error::Error,
40 fmt::{Display, Formatter},
41 path::{Path, PathBuf},
42 sync::Arc,
43};
44
45#[derive(Debug)]
47pub enum StyleResourceError {
48 Io(FileLoadError),
50
51 Visit(VisitError),
53}
54
55impl Display for StyleResourceError {
56 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
57 match self {
58 Self::Io(v) => {
59 write!(f, "A file load error has occurred {v:?}")
60 }
61 Self::Visit(v) => {
62 write!(
63 f,
64 "An error that may occur due to version incompatibilities. {v:?}"
65 )
66 }
67 }
68 }
69}
70
71impl From<FileLoadError> for StyleResourceError {
72 fn from(e: FileLoadError) -> Self {
73 Self::Io(e)
74 }
75}
76
77impl From<VisitError> for StyleResourceError {
78 fn from(e: VisitError) -> Self {
79 Self::Visit(e)
80 }
81}
82
83impl ResourceData for Style {
84 fn type_uuid(&self) -> Uuid {
85 <Self as TypeUuidProvider>::type_uuid()
86 }
87
88 fn save(&mut self, path: &Path) -> Result<(), Box<dyn Error>> {
89 let mut visitor = Visitor::new();
90 self.visit("Style", &mut visitor)?;
91 visitor.save_binary(path)?;
92 Ok(())
93 }
94
95 fn can_be_saved(&self) -> bool {
96 true
97 }
98}
99
100pub struct StyleLoader {
102 pub resource_manager: ResourceManager,
104}
105
106impl ResourceLoader for StyleLoader {
107 fn extensions(&self) -> &[&str] {
108 &["style"]
109 }
110
111 fn data_type_uuid(&self) -> Uuid {
112 <Style as TypeUuidProvider>::type_uuid()
113 }
114
115 fn load(&self, path: PathBuf, io: Arc<dyn ResourceIo>) -> BoxedLoaderFuture {
116 let resource_manager = self.resource_manager.clone();
117 Box::pin(async move {
118 let tile_set = Style::from_file(&path, io.as_ref(), resource_manager)
119 .await
120 .map_err(LoadError::new)?;
121 Ok(LoaderPayload::new(tile_set))
122 })
123 }
124}
125
126pub type StyleResource = Resource<Style>;
128
129pub trait StyleResourceExt {
131 fn set(&self, name: impl Into<ImmutableString>, property: impl Into<StyleProperty>);
133
134 fn get<P>(&self, name: impl Into<ImmutableString>) -> Option<P>
136 where
137 StyleProperty: IntoPrimitive<P>;
138
139 fn get_or<P>(&self, name: impl Into<ImmutableString>, default: P) -> P
141 where
142 StyleProperty: IntoPrimitive<P>;
143
144 fn get_or_default<P>(&self, name: impl Into<ImmutableString>) -> P
146 where
147 P: Default,
148 StyleProperty: IntoPrimitive<P>;
149
150 fn property<P>(&self, name: impl Into<ImmutableString>) -> StyledProperty<P>
152 where
153 P: Default,
154 StyleProperty: IntoPrimitive<P>;
155}
156
157impl StyleResourceExt for StyleResource {
158 fn set(&self, name: impl Into<ImmutableString>, property: impl Into<StyleProperty>) {
159 let mut state = self.state();
160 if let Some(data) = state.data() {
161 data.set(name, property);
162 } else {
163 Log::err("Unable to set style property, because the resource is invalid!")
164 }
165 }
166
167 fn get<P>(&self, name: impl Into<ImmutableString>) -> Option<P>
168 where
169 StyleProperty: IntoPrimitive<P>,
170 {
171 let state = self.state();
172 if let Some(data) = state.data_ref() {
173 data.get(name)
174 } else {
175 Log::err("Unable to get style property, because the resource is invalid!");
176 None
177 }
178 }
179
180 fn get_or<P>(&self, name: impl Into<ImmutableString>, default: P) -> P
181 where
182 StyleProperty: IntoPrimitive<P>,
183 {
184 let state = self.state();
185 if let Some(data) = state.data_ref() {
186 data.get_or(name, default)
187 } else {
188 Log::err("Unable to get style property, because the resource is invalid!");
189 default
190 }
191 }
192
193 fn get_or_default<P>(&self, name: impl Into<ImmutableString>) -> P
194 where
195 P: Default,
196 StyleProperty: IntoPrimitive<P>,
197 {
198 let state = self.state();
199 if let Some(data) = state.data_ref() {
200 data.get_or_default(name)
201 } else {
202 Log::err("Unable to get style property, because the resource is invalid!");
203 P::default()
204 }
205 }
206
207 fn property<P>(&self, name: impl Into<ImmutableString>) -> StyledProperty<P>
208 where
209 P: Default,
210 StyleProperty: IntoPrimitive<P>,
211 {
212 let state = self.state();
213 if let Some(data) = state.data_ref() {
214 data.property(name)
215 } else {
216 Log::err("Unable to get style property, because the resource is invalid!");
217 Default::default()
218 }
219 }
220}