1use std::borrow::{Borrow, BorrowMut};
28
29use crate::{
30 AccessAction, AccessRequest, App, Core, Extension, Extensions, InputEvent, Key, KeyCode,
31 KeyMods, KeyPress, MouseButton, Rect, Size, UiEvent, Vec2,
32};
33
34pub struct Drive<C: BorrowMut<Core> = Core> {
36 pub core: C,
37 pub exts: Extensions,
40 pub viewport: Size,
41 pub scale: f32,
43 framing: bool,
44 frame: u64,
45 now: f64,
46 log: Vec<String>,
47}
48
49impl<C: BorrowMut<Core>> Drive<C> {
50 pub fn new(mut core: C, w: f32, h: f32) -> Self {
53 core.borrow_mut().set_inspect(true);
54 Drive {
55 core,
56 exts: Extensions::new(),
57 viewport: Size::new(w, h),
58 scale: 1.0,
59 framing: false,
60 frame: 0,
61 now: 0.0,
62 log: Vec::new(),
63 }
64 }
65
66 pub fn framing(mut self) -> Self {
69 self.framing = true;
70 self
71 }
72
73 fn core(&mut self) -> &mut Core {
74 self.core.borrow_mut()
75 }
76
77 pub fn extension(&mut self, ns: &str, ext: impl Extension + 'static) -> Result<(), String> {
79 self.exts.push_as(ns, Box::new(ext))
80 }
81
82 pub fn frame(&mut self, app: &mut impl App) {
85 self.frame += 1;
86 let (viewport, scale, now) = (self.viewport, self.scale, self.now);
87 let core = self.core.borrow_mut();
88 core.set_time(now);
89 let mut ui = core.frame_with(viewport, scale, &mut self.exts);
90 app.view(&mut ui);
91 ui.finish();
92 let pending = self.core().take_pending_events();
93 self.deliver(app, pending);
94 }
95
96 pub fn advance(&mut self, secs: f64) {
98 self.now += secs;
99 }
100
101 pub fn frames(&self) -> u64 {
103 self.frame
104 }
105
106 pub fn key_of(&mut self, label: &str) -> Option<Key> {
108 self.core().key_of(label)
109 }
110
111 pub fn rect_of(&self, key: Key) -> Option<Rect> {
115 let core: &Core = self.core.borrow();
116 let hit = core
117 .interaction
118 .hits()
119 .iter()
120 .rev()
121 .find(|h| h.key == key)
122 .map(|h| h.rect);
123 hit.or_else(|| core.nodes().iter().find(|n| n.key == key).map(|n| n.rect))
124 }
125
126 pub fn texts_under(&self, label: &str) -> Vec<String> {
129 let nodes = Borrow::<Core>::borrow(&self.core).nodes();
130 let Some(at) = nodes.iter().position(|n| n.label.as_deref() == Some(label)) else {
131 return Vec::new();
132 };
133 nodes[at + 1..]
134 .iter()
135 .take_while(|n| n.depth > nodes[at].depth)
136 .filter_map(|n| n.text.clone())
137 .collect()
138 }
139
140 pub fn warnings(&mut self) -> Vec<String> {
143 self.core()
144 .take_warnings()
145 .into_iter()
146 .map(|w| format!("{}: {}", w.code, w.message))
147 .collect()
148 }
149
150 pub fn input(&mut self, app: &mut impl App, ev: InputEvent) -> Vec<UiEvent> {
152 let out = self.core().handle_input(ev);
153 self.deliver(app, out.clone());
154 out
155 }
156
157 fn done(&mut self, app: &mut impl App, out: Vec<UiEvent>) -> Vec<UiEvent> {
158 if self.framing {
159 self.frame(app);
160 }
161 out
162 }
163
164 pub fn move_to(&mut self, app: &mut impl App, x: f32, y: f32) -> Vec<UiEvent> {
166 let out = self.input(app, InputEvent::CursorMoved(Vec2::new(x, y)));
167 self.done(app, out)
168 }
169
170 pub fn hover(&mut self, app: &mut impl App, key: Key) -> Vec<UiEvent> {
172 let Some(c) = self.rect_of(key).map(|r| r.center()) else {
173 return Vec::new();
174 };
175 self.move_to(app, c.x, c.y)
176 }
177
178 fn press_at(&mut self, app: &mut impl App, at: Vec2, clicks: u8) -> Vec<UiEvent> {
179 let mut out = self.input(app, InputEvent::CursorMoved(at));
180 out.extend(self.input(app, InputEvent::mouse_down(clicks)));
181 out.extend(self.input(app, InputEvent::mouse_up()));
182 out
183 }
184
185 pub fn click(&mut self, app: &mut impl App, x: f32, y: f32) -> Vec<UiEvent> {
187 let out = self.press_at(app, Vec2::new(x, y), 1);
188 self.done(app, out)
189 }
190
191 pub fn double_click(&mut self, app: &mut impl App, x: f32, y: f32) -> Vec<UiEvent> {
194 let at = Vec2::new(x, y);
195 let mut out = self.press_at(app, at, 1);
196 out.extend(self.press_at(app, at, 2));
197 self.done(app, out)
198 }
199
200 pub fn click_key(&mut self, app: &mut impl App, key: Key) -> Vec<UiEvent> {
203 let out = self.input(
204 app,
205 InputEvent::Access(AccessRequest::new(key, AccessAction::Click)),
206 );
207 self.done(app, out)
208 }
209
210 pub fn drag(&mut self, app: &mut impl App, from: Vec2, to: Vec2) -> Vec<UiEvent> {
214 let mut out = self.input(app, InputEvent::CursorMoved(from));
215 out.extend(self.input(app, InputEvent::mouse_down(1)));
216 let past = Vec2::new(from.x + 8.0, from.y + 8.0);
217 out.extend(self.input(app, InputEvent::CursorMoved(past)));
218 out.extend(self.input(app, InputEvent::CursorMoved(to)));
219 if self.framing {
220 self.frame(app);
221 }
222 out.extend(self.input(app, InputEvent::mouse_up()));
223 self.done(app, out)
224 }
225
226 pub fn wheel(&mut self, app: &mut impl App, x: f32, y: f32, dx: f32, dy: f32) -> Vec<UiEvent> {
228 let mut out = self.input(app, InputEvent::CursorMoved(Vec2::new(x, y)));
229 out.extend(self.input(app, InputEvent::Scroll(Vec2::new(dx, dy))));
230 self.done(app, out)
231 }
232
233 pub fn scroll_gesture(
238 &mut self,
239 app: &mut impl App,
240 x: f32,
241 y: f32,
242 delta: Vec2,
243 begins: bool,
244 ) -> Vec<UiEvent> {
245 let mut out = self.input(app, InputEvent::CursorMoved(Vec2::new(x, y)));
246 out.extend(self.input(app, InputEvent::ScrollGesture { delta, begins }));
247 self.done(app, out)
248 }
249
250 pub fn button_click(
254 &mut self,
255 app: &mut impl App,
256 x: f32,
257 y: f32,
258 button: MouseButton,
259 ) -> Vec<UiEvent> {
260 let mut out = self.input(app, InputEvent::CursorMoved(Vec2::new(x, y)));
261 out.extend(self.input(app, InputEvent::MouseDown { button, clicks: 1 }));
262 out.extend(self.input(app, InputEvent::MouseUp { button }));
263 self.done(app, out)
264 }
265
266 pub fn key(&mut self, app: &mut impl App, name: &str, mods: KeyMods) -> Vec<UiEvent> {
273 let code = KeyCode::from_name(name).unwrap_or(KeyCode::Unknown);
274 let mut press = KeyPress::new(code, mods);
275 let chord = mods.ctrl || mods.alt || mods.super_key;
276 match code {
277 KeyCode::Char(c) if !chord => press = press.with_text(c.to_string()),
278 KeyCode::Space if !chord => press = press.with_text(" "),
279 _ => {}
280 }
281 let mut out = self.input(app, InputEvent::KeyDown(press.clone()));
282 if let Some(ev) = press.edit_event() {
283 out.extend(self.input(app, ev));
284 }
285 out.extend(self.input(app, InputEvent::KeyUp(press.released())));
286 self.done(app, out)
287 }
288
289 pub fn keys(&mut self, app: &mut impl App, seq: &str) -> Vec<UiEvent> {
292 let mut out = Vec::new();
293 for c in seq.chars() {
294 let name = if c == ' ' {
295 "space".to_string()
296 } else {
297 c.to_string()
298 };
299 out.extend(self.key(app, &name, KeyMods::NONE));
300 }
301 out
302 }
303
304 pub fn text(&mut self, app: &mut impl App, s: &str) -> Vec<UiEvent> {
306 let out = self.input(app, InputEvent::Text(s.to_string()));
307 self.done(app, out)
308 }
309
310 pub fn commit(&mut self, app: &mut impl App, s: &str) -> Vec<UiEvent> {
313 let out = self.input(app, InputEvent::Commit(s.to_string()));
314 self.done(app, out)
315 }
316
317 pub fn focus(&mut self, app: &mut impl App, key: Key) -> Vec<UiEvent> {
319 let out = self.input(
320 app,
321 InputEvent::Access(AccessRequest::new(key, AccessAction::Focus)),
322 );
323 self.done(app, out)
324 }
325
326 pub fn check(&self, cond: bool, what: &str) -> Result<(), String> {
329 if cond {
330 println!(" ok {what}");
331 Ok(())
332 } else {
333 Err(what.to_string())
334 }
335 }
336
337 pub fn log(&self) -> &[String] {
339 &self.log
340 }
341
342 fn deliver(&mut self, app: &mut impl App, events: Vec<UiEvent>) {
343 for ev in &events {
344 self.log.push(format!(
345 "{:>4} {:08x} {}",
346 self.frame,
347 ev.key.0 as u32,
348 crate::devtools::fmt_value(&ev.payload)
349 ));
350 }
351 let core = self.core.borrow_mut();
352 self.exts.route(events, |ev| app.on_event_with(ev, core));
353 }
354}