1use crate::dirty::Dirty;
2use crate::event::{Command, Event, EventPhase};
3use crate::geom::{Rect, Size};
4use crate::layout::Constraint;
5use crate::node::Node;
6use crate::render::RenderCx;
7use crate::style::Style;
8
9pub trait Component {
11 fn render(&self, cx: &mut RenderCx);
13
14 fn event(&mut self, _event: &Event, _cx: &mut EventCx) {}
16
17 fn style(&self) -> Style {
19 Style::default()
20 }
21
22 fn measure(&self, constraint: Constraint, _cx: &mut MeasureCx) -> Size {
26 Size {
27 width: constraint.max.width,
28 height: 1,
29 }
30 }
31
32 fn layout(&mut self, _rect: Rect, _cx: &mut LayoutCx) {}
36
37 fn mount(&mut self, _cx: &mut EventCx) {}
39 fn unmount(&mut self, _cx: &mut EventCx) {}
41 fn update(&mut self, _cx: &mut EventCx) {}
43
44 fn type_name(&self) -> &str {
46 std::any::type_name::<Self>()
47 .split("::")
48 .last()
49 .unwrap_or("Unknown")
50 }
51
52 fn id(&self) -> Option<&str> {
54 None
55 }
56
57 fn class(&self) -> Option<&str> {
59 None
60 }
61
62 fn focusable(&self) -> bool {
64 true
65 }
66
67 fn for_each_child(&self, _f: &mut dyn FnMut(&Node)) {}
69
70 fn for_each_child_mut(&mut self, _f: &mut dyn FnMut(&mut Node)) {}
72}
73
74pub struct EventCx<'a> {
79 pub(crate) node_dirty: &'a mut Dirty,
80 pub(crate) global_dirty: &'a mut Dirty,
81 pub(crate) quit: &'a mut bool,
82 pub(crate) phase: EventPhase,
83 pub(crate) propagation_stopped: &'a mut bool,
84 pub(crate) task_sender: Option<std::sync::mpsc::Sender<String>>,
85}
86
87impl<'a> EventCx<'a> {
88 pub(crate) fn new(
89 node_dirty: &'a mut Dirty,
90 global_dirty: &'a mut Dirty,
91 quit: &'a mut bool,
92 phase: EventPhase,
93 propagation_stopped: &'a mut bool,
94 ) -> Self {
95 Self {
96 node_dirty,
97 global_dirty,
98 quit,
99 phase,
100 propagation_stopped,
101 task_sender: None,
102 }
103 }
104
105 pub(crate) fn with_task_sender(
106 node_dirty: &'a mut Dirty,
107 global_dirty: &'a mut Dirty,
108 quit: &'a mut bool,
109 phase: EventPhase,
110 propagation_stopped: &'a mut bool,
111 task_sender: Option<std::sync::mpsc::Sender<String>>,
112 ) -> Self {
113 Self {
114 node_dirty,
115 global_dirty,
116 quit,
117 phase,
118 propagation_stopped,
119 task_sender,
120 }
121 }
122
123 pub fn phase(&self) -> EventPhase {
125 self.phase
126 }
127
128 pub fn stop_propagation(&mut self) {
130 *self.propagation_stopped = true;
131 }
132
133 pub fn invalidate_paint(&mut self) {
135 *self.node_dirty |= Dirty::PAINT;
136 *self.global_dirty |= Dirty::PAINT;
137 }
138
139 pub fn invalidate_layout(&mut self) {
141 *self.node_dirty |= Dirty::LAYOUT | Dirty::PAINT;
142 *self.global_dirty |= Dirty::LAYOUT | Dirty::PAINT;
143 }
144
145 pub fn invalidate(&mut self) {
147 self.invalidate_layout();
148 }
149
150 pub fn invalidate_tree(&mut self) {
152 *self.node_dirty |= Dirty::TREE | Dirty::LAYOUT | Dirty::PAINT;
153 *self.global_dirty |= Dirty::TREE | Dirty::LAYOUT | Dirty::PAINT;
154 }
155
156 pub fn copy_to_clipboard(&self, text: &str) {
161 use std::io::Write;
162 let seq = crate::clipboard::copy_to_clipboard_sequence(text);
163 let _ = std::io::stdout().write_all(seq.as_bytes());
164 let _ = std::io::stdout().flush();
165 }
166
167 pub fn quit(&mut self) {
169 *self.quit = true;
170 }
171
172 pub fn dispatch(&mut self, cmd: Command) {
174 crate::runtime::COMMAND_QUEUE.with(|q| {
175 q.borrow_mut().push(cmd);
176 });
177 }
178
179 pub fn toggle_debug() {
181 crate::runtime::DEBUG_MODE.with(|d| {
182 let current = *d.borrow();
183 *d.borrow_mut() = !current;
184 });
185 }
186
187 pub fn spawn<F>(&mut self, task: F)
189 where
190 F: FnOnce() -> String + Send + 'static,
191 {
192 if let Some(tx) = self.task_sender.clone() {
193 std::thread::spawn(move || {
194 let result = task();
195 let _ = tx.send(result);
196 });
197 }
198 }
199}
200
201pub struct MeasureCx {
203 pub constraint: Constraint,
204}
205
206pub struct LayoutCx<'a> {
208 children: &'a mut Vec<Node>,
209}
210
211impl<'a> LayoutCx<'a> {
212 pub(crate) fn new(children: &'a mut Vec<Node>) -> Self {
213 Self { children }
214 }
215
216 pub fn child_count(&self) -> usize {
218 self.children.len()
219 }
220
221 pub fn child_style(&self, index: usize) -> Option<Style> {
223 self.children.get(index).map(|n| n.component.style())
224 }
225
226 pub fn layout_child(&mut self, index: usize, rect: Rect) {
228 if let Some(child) = self.children.get_mut(index) {
229 child.layout(rect);
230 }
231 }
232
233 pub fn for_each_child(&mut self, mut f: impl FnMut(usize, &mut Node)) {
235 for (i, child) in self.children.iter_mut().enumerate() {
236 f(i, child);
237 }
238 }
239}