1use std::borrow::{Borrow, BorrowMut};
65
66use crate::{
67 AccessAction, AccessRequest, App, Core, Extension, Extensions, InputEvent, Key, KeyCode,
68 KeyMods, KeyPress, MouseButton, Rect, Size, UiEvent, Vec2,
69};
70
71pub struct Drive<C: BorrowMut<Core> = Core> {
76 pub core: C,
78 pub exts: Extensions,
81 pub viewport: Size,
83 pub scale: f32,
85 framing: bool,
86 frame: u64,
87 now: f64,
88 log: Vec<String>,
89}
90
91impl<C: BorrowMut<Core>> Drive<C> {
92 pub fn new(mut core: C, w: f32, h: f32) -> Self {
96 core.borrow_mut().set_inspect(true);
97 Drive {
98 core,
99 exts: Extensions::new(),
100 viewport: Size::new(w, h),
101 scale: 1.0,
102 framing: false,
103 frame: 0,
104 now: 0.0,
105 log: Vec::new(),
106 }
107 }
108
109 pub fn framing(mut self) -> Self {
112 self.framing = true;
113 self
114 }
115
116 fn core(&mut self) -> &mut Core {
117 self.core.borrow_mut()
118 }
119
120 pub fn extension(&mut self, ns: &str, ext: impl Extension + 'static) -> Result<(), String> {
122 self.exts.push_as(ns, Box::new(ext))
123 }
124
125 pub fn frame(&mut self, app: &mut impl App) {
128 self.frame += 1;
129 let (viewport, scale, now) = (self.viewport, self.scale, self.now);
130 let core = self.core.borrow_mut();
131 core.set_time(now);
132 let mut ui = core.frame_with(viewport, scale, &mut self.exts);
133 app.view(&mut ui);
134 ui.finish();
135 let pending = self.core().take_pending_events();
136 self.deliver(app, pending);
137 }
138
139 pub fn advance(&mut self, secs: f64) {
141 self.now += secs;
142 }
143
144 pub fn frames(&self) -> u64 {
146 self.frame
147 }
148
149 pub fn key_of(&mut self, label: &str) -> Option<Key> {
151 self.core().key_of(label)
152 }
153
154 pub fn rect_of(&self, key: Key) -> Option<Rect> {
158 let core: &Core = self.core.borrow();
159 let hit = core
160 .interaction
161 .hits()
162 .iter()
163 .rev()
164 .find(|h| h.key == key)
165 .map(|h| h.rect);
166 hit.or_else(|| core.nodes().iter().find(|n| n.key == key).map(|n| n.rect))
167 }
168
169 pub fn texts_under(&self, label: &str) -> Vec<String> {
172 let nodes = Borrow::<Core>::borrow(&self.core).nodes();
173 let Some(at) = nodes.iter().position(|n| n.label.as_deref() == Some(label)) else {
174 return Vec::new();
175 };
176 nodes[at + 1..]
177 .iter()
178 .take_while(|n| n.depth > nodes[at].depth)
179 .filter_map(|n| n.text.clone())
180 .collect()
181 }
182
183 pub fn warnings(&mut self) -> Vec<String> {
186 self.core()
187 .take_warnings()
188 .into_iter()
189 .map(|w| format!("{}: {}", w.code, w.message))
190 .collect()
191 }
192
193 pub fn input(&mut self, app: &mut impl App, ev: InputEvent) -> Vec<UiEvent> {
195 let out = self.core().handle_input(ev);
196 self.deliver(app, out.clone());
197 out
198 }
199
200 fn done(&mut self, app: &mut impl App, out: Vec<UiEvent>) -> Vec<UiEvent> {
201 if self.framing {
202 self.frame(app);
203 }
204 out
205 }
206
207 pub fn move_to(&mut self, app: &mut impl App, x: f32, y: f32) -> Vec<UiEvent> {
209 let out = self.input(app, InputEvent::CursorMoved(Vec2::new(x, y)));
210 self.done(app, out)
211 }
212
213 pub fn hover(&mut self, app: &mut impl App, key: Key) -> Vec<UiEvent> {
215 let Some(c) = self.rect_of(key).map(|r| r.center()) else {
216 return Vec::new();
217 };
218 self.move_to(app, c.x, c.y)
219 }
220
221 fn press_at(&mut self, app: &mut impl App, at: Vec2, clicks: u8) -> Vec<UiEvent> {
222 let mut out = self.input(app, InputEvent::CursorMoved(at));
223 out.extend(self.input(app, InputEvent::mouse_down(clicks)));
224 out.extend(self.input(app, InputEvent::mouse_up()));
225 out
226 }
227
228 pub fn click(&mut self, app: &mut impl App, x: f32, y: f32) -> Vec<UiEvent> {
230 let out = self.press_at(app, Vec2::new(x, y), 1);
231 self.done(app, out)
232 }
233
234 pub fn double_click(&mut self, app: &mut impl App, x: f32, y: f32) -> Vec<UiEvent> {
237 let at = Vec2::new(x, y);
238 let mut out = self.press_at(app, at, 1);
239 out.extend(self.press_at(app, at, 2));
240 self.done(app, out)
241 }
242
243 pub fn click_key(&mut self, app: &mut impl App, key: Key) -> Vec<UiEvent> {
246 let out = self.input(
247 app,
248 InputEvent::Access(AccessRequest::new(key, AccessAction::Click)),
249 );
250 self.done(app, out)
251 }
252
253 pub fn drag(&mut self, app: &mut impl App, from: Vec2, to: Vec2) -> Vec<UiEvent> {
257 let mut out = self.input(app, InputEvent::CursorMoved(from));
258 out.extend(self.input(app, InputEvent::mouse_down(1)));
259 let past = Vec2::new(from.x + 8.0, from.y + 8.0);
260 out.extend(self.input(app, InputEvent::CursorMoved(past)));
261 out.extend(self.input(app, InputEvent::CursorMoved(to)));
262 if self.framing {
263 self.frame(app);
264 }
265 out.extend(self.input(app, InputEvent::mouse_up()));
266 self.done(app, out)
267 }
268
269 pub fn wheel(&mut self, app: &mut impl App, x: f32, y: f32, dx: f32, dy: f32) -> Vec<UiEvent> {
271 let mut out = self.input(app, InputEvent::CursorMoved(Vec2::new(x, y)));
272 out.extend(self.input(app, InputEvent::Scroll(Vec2::new(dx, dy))));
273 self.done(app, out)
274 }
275
276 pub fn scroll_gesture(
281 &mut self,
282 app: &mut impl App,
283 x: f32,
284 y: f32,
285 delta: Vec2,
286 begins: bool,
287 ) -> Vec<UiEvent> {
288 let mut out = self.input(app, InputEvent::CursorMoved(Vec2::new(x, y)));
289 out.extend(self.input(app, InputEvent::ScrollGesture { delta, begins }));
290 self.done(app, out)
291 }
292
293 pub fn button_click(
296 &mut self,
297 app: &mut impl App,
298 x: f32,
299 y: f32,
300 button: MouseButton,
301 ) -> Vec<UiEvent> {
302 let mut out = self.input(app, InputEvent::CursorMoved(Vec2::new(x, y)));
303 out.extend(self.input(app, InputEvent::MouseDown { button, clicks: 1 }));
304 out.extend(self.input(app, InputEvent::MouseUp { button }));
305 self.done(app, out)
306 }
307
308 pub fn key(&mut self, app: &mut impl App, name: &str, mods: KeyMods) -> Vec<UiEvent> {
315 let code = KeyCode::from_name(name).unwrap_or(KeyCode::Unknown);
316 let mut press = KeyPress::new(code, mods);
317 let chord = mods.ctrl || mods.alt || mods.super_key;
318 match code {
319 KeyCode::Char(c) if !chord => press = press.with_text(c.to_string()),
320 KeyCode::Space if !chord => press = press.with_text(" "),
321 _ => {}
322 }
323 let mut out = self.input(app, InputEvent::KeyDown(press.clone()));
324 if let Some(ev) = press.edit_event() {
325 out.extend(self.input(app, ev));
326 }
327 out.extend(self.input(app, InputEvent::KeyUp(press.released())));
328 self.done(app, out)
329 }
330
331 pub fn keys(&mut self, app: &mut impl App, seq: &str) -> Vec<UiEvent> {
334 let mut out = Vec::new();
335 for c in seq.chars() {
336 let name = if c == ' ' {
337 "space".to_string()
338 } else {
339 c.to_string()
340 };
341 out.extend(self.key(app, &name, KeyMods::NONE));
342 }
343 out
344 }
345
346 pub fn text(&mut self, app: &mut impl App, s: &str) -> Vec<UiEvent> {
348 let out = self.input(app, InputEvent::Text(s.to_string()));
349 self.done(app, out)
350 }
351
352 pub fn commit(&mut self, app: &mut impl App, s: &str) -> Vec<UiEvent> {
355 let out = self.input(app, InputEvent::Commit(s.to_string()));
356 self.done(app, out)
357 }
358
359 pub fn focus(&mut self, app: &mut impl App, key: Key) -> Vec<UiEvent> {
361 let out = self.input(
362 app,
363 InputEvent::Access(AccessRequest::new(key, AccessAction::Focus)),
364 );
365 self.done(app, out)
366 }
367
368 pub fn check(&self, cond: bool, what: &str) -> Result<(), String> {
371 if cond {
372 println!(" ok {what}");
373 Ok(())
374 } else {
375 Err(what.to_string())
376 }
377 }
378
379 pub fn log(&self) -> &[String] {
381 &self.log
382 }
383
384 fn deliver(&mut self, app: &mut impl App, events: Vec<UiEvent>) {
385 for ev in &events {
386 self.log.push(format!(
387 "{:>4} {:08x} {}",
388 self.frame,
389 ev.key.0 as u32,
390 crate::devtools::fmt_value(&ev.payload)
391 ));
392 }
393 let core = self.core.borrow_mut();
394 self.exts.route(events, |ev| app.on_event_with(ev, core));
395 }
396}