1use feather_macro::*;
5use feather_ui::color::sRGB;
6use feather_ui::component::image::Image;
7use feather_ui::component::region::Region;
8use feather_ui::component::shape::{Shape, ShapeKind};
9use feather_ui::component::window::Window;
10use feather_ui::layout::{fixed, leaf};
11use feather_ui::persist::{FnPersist2, FnPersistStore};
12use feather_ui::{
13 AbsPoint, AbsRect, App, DAbsRect, DPoint, DRect, PxRect, RelRect, ScopeID, SourceID,
14 UNSIZED_AXIS, gen_id, im, winit,
15};
16use std::path::PathBuf;
17use std::sync::Arc;
18
19#[derive(Default, Empty, Area, Anchor, ZIndex, Limits, RLimits, Padding)]
20struct FixedData {
21 area: DRect,
22 anchor: DPoint,
23 limits: feather_ui::DLimits,
24 rlimits: feather_ui::RelLimits,
25 padding: DAbsRect,
26 zindex: i32,
27}
28
29impl fixed::Prop for FixedData {}
30impl fixed::Child for FixedData {}
31impl leaf::Prop for FixedData {}
32impl leaf::Padded for FixedData {}
33
34struct BasicApp {}
35
36impl FnPersistStore for BasicApp {
37 type Store = im::HashMap<Arc<SourceID>, Option<Window>>;
38}
39
40impl FnPersist2<(), ScopeID<'_>, im::HashMap<Arc<SourceID>, Option<Window>>> for BasicApp {
41 fn init(&self) -> Self::Store {
42 im::HashMap::new()
43 }
44
45 fn call(
46 &mut self,
47 _: Self::Store,
48 _: (),
49 mut scope: ScopeID<'_>,
50 ) -> (Self::Store, im::HashMap<Arc<SourceID>, Option<Window>>) {
51 let pixel = Shape::<DRect, { ShapeKind::RoundRect as u8 }>::new(
52 scope.create(),
53 PxRect::new(1.0, 1.0, 2.0, 2.0).into(),
54 0.0,
55 0.0,
56 wide::f32x4::splat(0.0),
57 sRGB::new(1.0, 1.0, 1.0, 1.0),
58 sRGB::transparent(),
59 feather_ui::DAbsPoint::zero(),
60 );
61
62 let mut children: im::Vector<Option<Box<feather_ui::component::ChildOf<dyn fixed::Prop>>>> =
63 im::Vector::new();
64 children.push_back(Some(Box::new(pixel)));
65
66 let mut genimage = |pos: AbsPoint,
67 w: Option<f32>,
68 h: Option<f32>,
69 res: &dyn feather_ui::resource::Location,
70 size: Option<AbsPoint>| {
71 Image::<DRect>::new(
72 scope.create(),
73 AbsRect::new(
74 pos.x,
75 pos.y,
76 w.map(|x| x + pos.x).unwrap_or_default(),
77 h.map(|y| y + pos.y).unwrap_or_default(),
78 ) + RelRect::new(
79 0.0,
80 0.0,
81 if w.is_none() { UNSIZED_AXIS } else { 0.0 },
82 if h.is_none() { UNSIZED_AXIS } else { 0.0 },
83 ),
84 res,
85 size.unwrap_or_default().into(),
86 false,
87 )
88 };
89
90 #[cfg(feature = "png")]
91 {
92 let testimage = PathBuf::from("./premul_test.png");
93
94 children.push_back(Some(Box::new(genimage(
95 AbsPoint::new(0.0, 0.0),
96 Some(100.0),
97 Some(100.0),
98 &testimage,
99 None,
100 ))));
101
102 children.push_back(Some(Box::new(genimage(
103 AbsPoint::new(100.0, 0.0),
104 None,
105 Some(100.0),
106 &testimage,
107 None,
108 ))));
109
110 children.push_back(Some(Box::new(genimage(
111 AbsPoint::new(0.0, 100.0),
112 None,
113 None,
114 &testimage,
115 Some(AbsPoint::new(100.0, 100.0)),
116 ))));
117
118 children.push_back(Some(Box::new(genimage(
119 AbsPoint::new(100.0, 100.0),
120 None,
121 None,
122 &testimage,
123 None,
124 ))));
125 }
126
127 #[cfg(feature = "svg")]
128 {
129 let testsvg = PathBuf::from("./FRI_logo.svg");
130
131 children.push_back(Some(Box::new(genimage(
132 AbsPoint::new(200.0, 0.0),
133 Some(100.0),
134 Some(100.0),
135 &testsvg,
136 None,
137 ))));
138
139 children.push_back(Some(Box::new(genimage(
140 AbsPoint::new(300.0, 0.0),
141 None,
142 Some(100.0),
143 &testsvg,
144 None,
145 ))));
146
147 children.push_back(Some(Box::new(genimage(
148 AbsPoint::new(200.0, 100.0),
149 None,
150 None,
151 &testsvg,
152 Some(AbsPoint::new(100.0, 100.0)),
153 ))));
154
155 children.push_back(Some(Box::new(genimage(
156 AbsPoint::new(300.0, 100.0),
157 None,
158 None,
159 &testsvg,
160 None,
161 ))));
162 }
163
164 #[cfg(feature = "png")]
165 {
166 let testimage = PathBuf::from("./test_color.png");
167
168 children.push_back(Some(Box::new(genimage(
169 AbsPoint::new(0.0, 200.0),
170 Some(100.0),
171 Some(100.0),
172 &testimage,
173 None,
174 ))));
175
176 children.push_back(Some(Box::new(genimage(
177 AbsPoint::new(100.0, 200.0),
178 Some(100.0),
179 None,
180 &testimage,
181 None,
182 ))));
183
184 children.push_back(Some(Box::new(genimage(
185 AbsPoint::new(0.0, 300.0),
186 None,
187 None,
188 &testimage,
189 Some(AbsPoint::new(100.0, 100.0)),
190 ))));
191
192 children.push_back(Some(Box::new(genimage(
193 AbsPoint::new(100.0, 300.0),
194 None,
195 None,
196 &testimage,
197 None,
198 ))));
199 }
200
201 #[cfg(feature = "jxl")]
202 {
203 let testimage = PathBuf::from("./dice.jxl");
204
205 children.push_back(Some(Box::new(genimage(
206 AbsPoint::new(200.0, 200.0),
207 Some(100.0),
208 Some(100.0),
209 &testimage,
210 None,
211 ))));
212
213 children.push_back(Some(Box::new(genimage(
214 AbsPoint::new(300.0, 200.0),
215 Some(100.0),
216 None,
217 &testimage,
218 None,
219 ))));
220
221 children.push_back(Some(Box::new(genimage(
222 AbsPoint::new(200.0, 300.0),
223 None,
224 None,
225 &testimage,
226 Some(AbsPoint::new(100.0, 100.0)),
227 ))));
228
229 children.push_back(Some(Box::new(genimage(
230 AbsPoint::new(300.0, 300.0),
231 None,
232 None,
233 &testimage,
234 None,
235 ))));
236 }
237
238 let region = Region::new(
239 gen_id!(scope),
240 FixedData {
241 area: AbsRect::new(10.0, 10.0, -10.0, -10.0) + RelRect::new(0.0, 0.0, 1.0, 1.0),
242
243 zindex: 0,
244 ..Default::default()
245 },
246 children,
247 );
248
249 #[cfg(feature = "svg")]
250 let icon = Some(
251 feather_ui::resource::load_icon(&std::path::PathBuf::from("./FRI_logo.svg")).unwrap(),
252 );
253 #[cfg(not(feature = "svg"))]
254 let icon = None;
255
256 let window = Window::new(
257 gen_id!(scope),
258 winit::window::Window::default_attributes()
259 .with_title(env!("CARGO_CRATE_NAME"))
260 .with_resizable(true)
261 .with_window_icon(icon),
262 Box::new(region),
263 );
264
265 let mut store = im::HashMap::new();
266 store.insert(window.id.clone(), Some(window));
267 let windows = store.clone();
268 (store, windows)
269 }
270}
271
272fn main() {
273 let (mut app, event_loop, _, _) =
274 App::<(), BasicApp>::new::<()>((), Vec::new(), BasicApp {}, |_| ()).unwrap();
275
276 event_loop.run_app(&mut app).unwrap();
277}