lgui_core/core/layout/
dirty.rs1use std::collections::HashSet;
2
3use super::{HostTree, UiEvent, UiId, UiRect};
4
5#[derive(Clone, Debug, Default)]
6pub struct DirtySet {
7 ids: HashSet<UiId>,
8 rects: Vec<UiRect>,
9}
10
11impl DirtySet {
12 pub fn new() -> Self {
13 Self {
14 ids: HashSet::new(),
15 rects: Vec::new(),
16 }
17 }
18
19 pub fn mark_id(&mut self, id: UiId) {
20 self.ids.insert(id);
21 }
22
23 pub fn mark_rect(&mut self, rect: UiRect) {
24 self.rects.push(rect);
25 }
26
27 pub fn is_empty(&self) -> bool {
28 self.ids.is_empty() && self.rects.is_empty()
29 }
30
31 pub fn bounds(&self, tree: &HostTree) -> Option<UiRect> {
32 let mut bounds = tree.paint_bounds(self.ids.iter().cloned());
33 for rect in &self.rects {
34 bounds = Some(bounds.map_or(*rect, |current| current.union(*rect)));
35 }
36 bounds
37 }
38}
39
40#[derive(Default)]
41pub struct DirtyTracker {
42 dirty: DirtySet,
43}
44
45impl DirtyTracker {
46 pub fn mark_id(&mut self, id: UiId) {
47 self.dirty.mark_id(id);
48 }
49
50 pub fn mark_rect(&mut self, rect: UiRect) {
51 self.dirty.mark_rect(rect);
52 }
53
54 pub fn mark_event(&mut self, event: UiEvent) {
55 match event {
56 UiEvent::HoverChanged { previous, current } => {
57 if let Some(id) = previous {
58 self.mark_id(id);
59 }
60 if let Some(hit) = current {
61 self.mark_id(hit.id);
62 }
63 }
64 UiEvent::PressedChanged { previous, current } => {
65 if let Some(id) = previous {
66 self.mark_id(id);
67 }
68 if let Some(hit) = current {
69 self.mark_id(hit.id);
70 }
71 }
72 UiEvent::Clicked(hit) => self.mark_id(hit.id),
73 UiEvent::Wheel { hit, .. } => self.mark_id(hit.id),
74 UiEvent::TextInput { target, .. }
75 | UiEvent::ImeStarted { target }
76 | UiEvent::ImeUpdated { target, .. }
77 | UiEvent::ImeEnded { target }
78 | UiEvent::Keyboard { target, .. }
79 | UiEvent::SemanticValue { target, .. }
80 | UiEvent::SemanticAction { target, .. } => self.mark_id(target),
81 UiEvent::PointerPressed { hit, .. } => self.mark_id(hit.id),
82 UiEvent::PointerMoved { .. } => {}
86 UiEvent::PointerDragged { hit, .. } => self.mark_id(hit.id),
87 UiEvent::PointerReleased { hit, .. } => self.mark_id(hit.id),
88 UiEvent::FocusChanged { previous, current } => {
89 if let Some(id) = previous {
90 self.mark_id(id);
91 }
92 if let Some(hit) = current {
93 self.mark_id(hit.id);
94 }
95 }
96 UiEvent::PointerLeft { previous } => {
97 if let Some(id) = previous {
98 self.mark_id(id);
99 }
100 }
101 }
102 }
103
104 pub fn mark_animation_ids(&mut self, ids: impl IntoIterator<Item = UiId>) {
105 for id in ids {
106 self.mark_id(id);
107 }
108 }
109
110 pub fn take(&mut self) -> DirtySet {
111 std::mem::take(&mut self.dirty)
112 }
113}