1#![allow(dead_code)]
2
3pub mod entity;
4pub use entity::*;
5
6pub mod tree;
7pub use tree::*;
8
9pub mod storage;
10pub use storage::*;
11
12pub mod style;
13pub use style::*;
14
15pub mod data;
16pub use data::*;
17
18pub mod animation;
19pub use animation::*;
20
21pub mod mouse;
22pub use mouse::*;
23
24pub mod resource;
25pub use resource::*;
26
27
28pub use crate::events::{Builder, Event, Propagation, Widget, EventHandler};
29pub use crate::window_event::WindowEvent;
30
31use femtovg::FontId;
32
33use std::collections::VecDeque;
34
35use fnv::FnvHashMap;
36
37#[derive(Clone)]
38pub struct Fonts {
39 pub regular: Option<FontId>,
40 pub bold: Option<FontId>,
41 pub icons: Option<FontId>,
42 pub emoji: Option<FontId>,
43 pub arabic: Option<FontId>,
44}
45
46pub struct State {
47 pub(crate) entity_manager: EntityManager,
49 pub tree: Tree,
51 pub style: Style,
53 pub data: CachedData,
55 pub mouse: MouseState,
57 pub modifiers: ModifiersState,
59
60 pub hovered: Entity,
62 pub active: Entity,
64 pub captured: Entity,
66 pub focused: Entity,
68
69
70 pub(crate) callbacks: FnvHashMap<Entity, Box<dyn FnMut(&mut Box<dyn EventHandler>, &mut Self, Entity)>>,
71
72 pub event_handlers: FnvHashMap<Entity, Box<dyn EventHandler>>,
74
75 pub(crate) removed_entities: Vec<Entity>,
77
78 pub event_queue: VecDeque<Event>,
80
81 pub fonts: Fonts, pub(crate) resource_manager: ResourceManager, pub needs_restyle: bool,
87 pub needs_relayout: bool,
88 pub needs_redraw: bool,
89
90 pub listeners: FnvHashMap<Entity, Box<dyn Fn(&mut dyn EventHandler, &mut State, Entity, &mut Event)>>,
91}
92
93impl State {
94 pub fn new() -> Self {
95 let mut entity_manager = EntityManager::new();
96 let _root = entity_manager.create_entity();
97 let tree = Tree::new();
98 let mut style = Style::default();
99 let mut data = CachedData::default();
100 let mouse = MouseState::default();
101 let modifiers = ModifiersState::default();
102
103 let root = Entity::root();
104
105 data.add(root);
106 style.add(root);
107
108 style.clip_widget.set(root, root);
109
110 style.background_color.insert(root, Color::rgb(80, 80, 80)).expect("");
111
112
113
114 State {
115 entity_manager,
116 tree,
117 style,
118 data,
119 mouse,
120 modifiers,
121 hovered: Entity::root(),
122 active: Entity::null(),
123 captured: Entity::null(),
124 focused: Entity::root(),
125 callbacks: FnvHashMap::default(),
126 event_handlers: FnvHashMap::default(),
127 event_queue: VecDeque::new(),
128 removed_entities: Vec::new(),
129 fonts: Fonts {
130 regular: None,
131 bold: None,
132 icons: None,
133 emoji: None,
134 arabic: None,
135 },
136 resource_manager: ResourceManager::new(),
137 needs_restyle: false,
138 needs_relayout: false,
139 needs_redraw: false,
140
141 listeners: FnvHashMap::default(),
142 }
143 }
144
145 pub(crate) fn build<'a, T>(&'a mut self, entity: Entity, event_handler: T) -> Builder<'a,T>
146 where
147 T: EventHandler + 'static,
148 {
149 self.event_handlers.insert(entity, Box::new(event_handler));
150
151 Builder::new(self, entity)
152 }
153
154 pub fn query<E: EventHandler>(&mut self, entity: Entity) -> Option<&mut E> {
155 if let Some(event_handler) = self.event_handlers.get_mut(&entity) {
156 event_handler.downcast::<E>()
157 } else {
158 None
159 }
160 }
161
162 pub fn add_stylesheet(&mut self, path: &str) -> Result<(), std::io::Error> {
173 let style_string = std::fs::read_to_string(path.clone())?;
174 self.resource_manager.stylesheets.push(path.to_owned());
175 self.style.parse_theme(&style_string);
176
177 Ok(())
178 }
179
180 pub fn add_theme(&mut self, theme: &str) {
181 self.resource_manager.themes.push(theme.to_owned());
182
183 self.reload_styles().expect("Failed to reload styles");
184 }
185
186 pub fn add_style_rule(&mut self, style_rule: StyleRule) {
196 self.style.add_rule(style_rule);
197 self.insert_event(Event::new(WindowEvent::Restyle).target(Entity::root()));
198 self.insert_event(Event::new(WindowEvent::Relayout).target(Entity::root()));
199 self.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
200 }
201
202 pub fn add_font(&mut self, _name: &str, _path: &str) {
209 println!("Add an font to resource manager");
210 }
211
212 pub fn reload_styles(&mut self) -> Result<(), std::io::Error> {
215 if self.resource_manager.themes.is_empty() && self.resource_manager.stylesheets.is_empty() {
216 return Ok(());
217 }
218
219 self.style.remove_all();
220
221 let mut overall_theme = String::new();
222
223 for theme in self.resource_manager.themes.iter() {
225 overall_theme += theme;
227 }
228
229 for stylesheet in self.resource_manager.stylesheets.iter() {
231 let theme = std::fs::read_to_string(stylesheet)?;
232 overall_theme += &theme;
233 }
234
235 self.style.parse_theme(&overall_theme);
236
237 self.insert_event(Event::new(WindowEvent::Restyle).target(Entity::root()));
238 self.insert_event(Event::new(WindowEvent::Relayout).target(Entity::root()));
239 self.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
240
241 Ok(())
242 }
243
244 pub fn insert_event(&mut self, event: Event) {
254 if event.unique {
255 self.event_queue.retain(|e| e != &event);
256 }
257
258 self.event_queue.push_back(event);
259 }
260
261 pub fn capture(&mut self, entity: Entity) {
263 if entity != Entity::null() && self.captured != entity {
265 self.insert_event(
266 Event::new(WindowEvent::MouseCaptureEvent)
267 .target(entity)
268 .propagate(Propagation::Direct),
269 );
270 }
271
272 if self.captured != Entity::null() && self.captured != entity {
273 self.insert_event(
274 Event::new(WindowEvent::MouseCaptureOutEvent)
275 .target(self.captured)
276 .propagate(Propagation::Direct),
277 );
278 }
279
280 self.captured = entity;
281 self.active = entity;
282 }
283
284 pub fn release(&mut self, id: Entity) {
286
287 if self.captured == id {
288 self.insert_event(
289 Event::new(WindowEvent::MouseCaptureOutEvent)
290 .target(self.captured)
291 .propagate(Propagation::Direct),
292 );
293
294 self.captured = Entity::null();
297 self.active = Entity::null();
298 }
299
300 }
301
302 pub fn set_focus(&mut self, entity: Entity) {
303 if self.focused != entity {
304 if self.focused != Entity::null() {
305 self.focused.set_focus(self, false);
306 self.insert_event(Event::new(WindowEvent::FocusOut).target(self.focused));
307 }
308
309 if entity != Entity::null() {
310 self.focused = entity;
311 entity.set_focus(self, true);
312 self.insert_event(Event::new(WindowEvent::FocusIn).target(self.focused));
313 }
314 }
315 }
316
317 pub(crate) fn add(&mut self, parent: Entity) -> Entity {
319 let entity = self
320 .entity_manager
321 .create_entity()
322 .expect("Failed to create entity");
323 self.tree.add(entity, parent).expect("");
324 self.data.add(entity);
325 self.style.add(entity);
326
327 self.insert_event(Event::new(WindowEvent::Restyle).target(Entity::root()));
328 self.insert_event(Event::new(WindowEvent::Relayout).target(Entity::root()));
329 self.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
330
331 entity
332 }
333
334 pub fn remove(&mut self, entity: Entity) {
336 let delete_list = entity.branch_iter(&self.tree).collect::<Vec<_>>();
338
339 for entity in delete_list.iter().rev() {
340 self.tree.remove(*entity).expect("");
341 self.data.remove(*entity);
343 self.style.remove(*entity);
344 self.removed_entities.push(*entity);
345 self.entity_manager.destroy_entity(*entity);
346 }
347
348 self.insert_event(Event::new(WindowEvent::Restyle).target(Entity::root()));
349 self.insert_event(Event::new(WindowEvent::Relayout).target(Entity::root()));
350 self.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
351 }
352
353 pub fn apply_animations(&mut self) -> bool {
356
357 let time = std::time::Instant::now();
358
359 self.style.background_color.animate(time);
360
361 self.style.left.animate(time);
363 self.style.right.animate(time);
364 self.style.top.animate(time);
365 self.style.bottom.animate(time);
366
367 self.style.min_left.animate(time);
369 self.style.max_left.animate(time);
370 self.style.min_right.animate(time);
371 self.style.max_right.animate(time);
372 self.style.min_top.animate(time);
373 self.style.max_top.animate(time);
374 self.style.min_bottom.animate(time);
375 self.style.max_bottom.animate(time);
376
377 self.style.width.animate(time);
379 self.style.height.animate(time);
380
381 self.style.min_width.animate(time);
383 self.style.max_width.animate(time);
384 self.style.min_height.animate(time);
385 self.style.max_height.animate(time);
386
387 self.style.child_left.animate(time);
389 self.style.child_right.animate(time);
390 self.style.child_top.animate(time);
391 self.style.child_bottom.animate(time);
392 self.style.row_between.animate(time);
393 self.style.col_between.animate(time);
394
395 self.style.opacity.animate(time);
396 self.style.rotate.animate(time);
397
398 self.style.border_radius_top_left.animate(time);
400 self.style.border_radius_top_right.animate(time);
401 self.style.border_radius_bottom_left.animate(time);
402 self.style.border_radius_bottom_right.animate(time);
403
404 self.style.border_width.animate(time);
406 self.style.border_color.animate(time);
407
408 self.style.font_size.animate(time);
410 self.style.font_color.animate(time);
411
412
413 self.style.background_color.has_animations()
414 || self.style.font_color.has_animations()
415 || self.style.left.has_animations()
417 || self.style.right.has_animations()
418 || self.style.top.has_animations()
419 || self.style.bottom.has_animations()
420 || self.style.min_left.has_animations()
422 || self.style.max_left.has_animations()
423 || self.style.min_right.has_animations()
424 || self.style.max_right.has_animations()
425 || self.style.min_top.has_animations()
426 || self.style.max_top.has_animations()
427 || self.style.min_bottom.has_animations()
428 || self.style.max_bottom.has_animations()
429 || self.style.width.has_animations()
431 || self.style.height.has_animations()
432 || self.style.min_width.has_animations()
434 || self.style.max_width.has_animations()
435 || self.style.min_height.has_animations()
436 || self.style.max_height.has_animations()
437 || self.style.child_left.has_animations()
439 || self.style.child_right.has_animations()
440 || self.style.child_top.has_animations()
441 || self.style.child_bottom.has_animations()
442 || self.style.row_between.has_animations()
443 || self.style.col_between.has_animations()
444 || self.style.opacity.has_animations()
446 || self.style.rotate.has_animations()
447 || self.style.border_radius_top_left.has_animations()
449 || self.style.border_radius_top_right.has_animations()
450 || self.style.border_radius_bottom_left.has_animations()
451 || self.style.border_radius_bottom_right.has_animations()
452 || self.style.border_width.has_animations()
454 || self.style.border_color.has_animations()
455
456 }
457}