1
2pub mod layout;
3use std::any::Any;
4
5pub use layout::*;
6
7pub mod memory;
8pub use memory::*;
9
10pub mod style;
11use style::*;
12
13pub mod input;
14pub use input::*;
15
16mod paint;
17
18mod tree;
19pub use tree::*;
20
21mod cursor;
22pub use cursor::*;
23
24mod clipboard;
25
26use crate::{Color, Rect, Vec2};
27
28use super::{text::FontId, Margin, Painter, PerAxis, RenderResources, Stroke, TSTransform};
29
30pub struct UI<'a, 'b> {
31 input: &'a Input,
32 memory: &'a mut Memory,
33 style: Style,
34
35 render_resources: &'a mut RenderResources<'b>,
36 clipboard: Option<&'a mut arboard::Clipboard>,
37
38 window_size: Vec2,
39
40 tree: UITree,
42 parent_stack: Vec<UIRef>,
43 curr_sibling: UIRef,
44
45 pub(crate) request_redraw: bool,
47 pub(crate) cursor: CursorIcon,
48 pub(crate) request_ime: Option<UIRef>
49}
50
51impl<'a, 'b> UI<'a, 'b> {
52
53 pub(crate) fn new(input: &'a Input, memory: &'a mut Memory, render_resources: &'a mut RenderResources<'b>, clipboard: Option<&'a mut arboard::Clipboard>, window_size: Vec2, tree: UITree, layer: UIRef) -> Self {
54 Self {
55 input,
56 memory,
57 style: Style::new(),
58 render_resources,
59 clipboard,
60 window_size,
61 tree,
62 parent_stack: vec![layer],
63 curr_sibling: UIRef::Null,
64 request_redraw: false,
65 cursor: CursorIcon::default(),
66 request_ime: None
67 }
68 }
69
70 pub(crate) fn tree(self) -> UITree {
71 self.tree
72 }
73
74 pub fn curr_parent(&self) -> UIRef {
75 let Some(parent) = self.parent_stack.last() else { panic!("no parents in parent stack. ui in an invalid state.") };
76 *parent
77 }
78
79 pub fn node(&mut self, params: UINodeParams) -> Response {
80 let parent_ref = self.curr_parent();
81 let parent = self.tree.get(parent_ref);
82
83 let mut new_node = UINode::new(parent.id, parent.n_children, params);
84 new_node.prev = self.curr_sibling;
85 new_node.parent = parent_ref;
86
87 let new_node = self.tree.add_node(new_node);
88
89 match self.curr_sibling {
90 UIRef::Null => {
91 self.tree.get_mut(parent_ref).first_child = new_node;
92 },
93 UIRef::Some(_) => {
94 self.tree.get_mut(self.curr_sibling).next = new_node;
95 },
96 }
97
98 self.curr_sibling = new_node;
99 self.tree.get_mut(parent_ref).last_child = new_node;
100 self.tree.get_mut(parent_ref).n_children += 1;
101
102 let id = self.tree.get(new_node).id;
103 let interaction = self.memory.get::<Interaction>(id);
104
105 Response {
106 id,
107 node_ref: new_node,
108 hovered: interaction.hovered,
109 through_hovered: interaction.through_hovered,
110 l_mouse: interaction.l_mouse,
111 r_mouse: interaction.r_mouse,
112 scroll: interaction.scroll
113 }
114 }
115
116 pub(crate) fn push_parent(&mut self, parent: UIRef) {
117 self.parent_stack.push(parent);
118 self.curr_sibling = self.tree.get(parent).last_child;
119 }
120
121 pub(crate) fn pop_parent(&mut self) {
122 self.parent_stack.pop();
123 if self.parent_stack.is_empty() {
124 panic!("ui parent stack underflow!");
125 }
126 self.curr_sibling = self.tree.get(self.curr_parent()).last_child;
127 }
128
129 pub fn with_parent<R, F: FnOnce(&mut Self) -> R>(&mut self, parent: UIRef, body: F) -> R {
130 self.push_parent(parent);
131 let body_result = body(self);
132 self.pop_parent();
133 body_result
134 }
135
136 pub fn with_node<R, F: FnOnce(&mut UI) -> R>(&mut self, params: UINodeParams, body: F) -> (Response, R) {
137 let resp = self.node(params);
138 (resp, self.with_parent(resp.node_ref, body))
139 }
140
141 pub fn layer<R, F: FnOnce(&mut Self) -> R>(&mut self, body: F) -> (UIRef, R) {
142 let layer = self.tree.add_layer(self.window_size);
143 (layer, self.with_parent(layer, body))
144 }
145
146 pub fn get_parent_ref(&self, node: UIRef) -> UIRef {
147 self.tree.get(node).parent
148 }
149
150 pub fn get_parent_id(&self, node: UIRef) -> Id {
151 let parent_ref = self.get_parent_ref(node);
152 self.tree.get(parent_ref).id
153 }
154
155 pub fn input(&self) -> &Input {
156 &self.input
157 }
158
159 pub fn window_size(&self) -> Vec2 {
160 self.window_size
161 }
162
163 pub fn memory(&mut self) -> &mut Memory {
164 &mut self.memory
165 }
166
167 pub fn style<T: Default + Any>(&mut self) -> &T {
168 self.style.get()
169 }
170
171 pub fn with_style<T: Default + Any, F: FnOnce(&mut Self)>(&mut self, style: T, body: F) {
172 self.style.push(style);
173 body(self);
174 self.style.pop();
175 }
176
177 pub fn set_size(&mut self, node: UIRef, width: Size, height: Size) {
178 self.tree.get_mut(node).params.size = PerAxis::new(width, height);
179 }
180
181 pub fn set_margin(&mut self, node: UIRef, margin: Margin) {
182 self.tree.get_mut(node).params.margin = margin;
183 }
184
185 pub fn set_fill(&mut self, node: UIRef, fill: Color) {
186 self.tree.get_mut(node).params.fill = fill;
187 }
188
189 pub fn set_stroke(&mut self, node: UIRef, stroke: Stroke) {
190 self.tree.get_mut(node).params.stroke = stroke;
191 }
192
193 pub fn set_transform(&mut self, node: UIRef, transform: TSTransform) {
194 self.tree.get_mut(node).params.transform = transform;
195 }
196
197 pub fn set_text<S: Into<String>>(&mut self, node: UIRef, text: S) {
198 self.tree.get_mut(node).params.text = Some(text.into());
199 }
200
201 pub fn set_sense_mouse(&mut self, node: UIRef, mouse: bool) {
202 self.tree.get_mut(node).params.mouse = mouse;
203 }
204
205 pub fn set_on_paint<F: FnOnce(&mut Painter, Rect) + 'static>(&mut self, node: UIRef, on_paint: F) {
206 self.tree.get_mut(node).params.on_paint = Some(Box::new(on_paint));
207 }
208
209 pub fn request_redraw(&mut self) {
210 self.request_redraw = true;
211 }
212
213 pub fn set_cursor(&mut self, cursor: CursorIcon) {
214 self.cursor = cursor;
215 }
216
217 pub fn request_ime(&mut self, node: UIRef) {
218 self.request_ime = Some(node);
219 }
220
221 pub fn wgpu_device(&mut self) -> &wgpu::Device {
223 &self.render_resources.device
224 }
225
226 pub fn wgpu_queue(&mut self) -> &wgpu::Queue {
228 &self.render_resources.queue
229 }
230
231 pub fn font_system(&mut self, font_id: FontId) -> Option<&mut cosmic_text::FontSystem> {
233 let font = self.render_resources.text_resources.fonts.get_mut(&font_id)?;
234 Some(&mut font.font_system)
235 }
236
237 pub fn text_font(&self) -> FontId {
238 self.render_resources.text_resources.text_font
239 }
240
241 pub fn icon_font(&self) -> FontId {
242 self.render_resources.text_resources.icon_font
243 }
244
245}