c40225838c
- card areas now cover their card, so egui sees the pointer over them (wheel scroll in note, diff, sidebar, assistant) - Preview button on pending changes opens a full-window review; Side by side / Unified toggle - math: log/ln/det/trig operators, \operatorname, \bmod, \pmod, \iint, \xrightarrow, negated relations Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
61 lines
2.9 KiB
Rust
61 lines
2.9 KiB
Rust
//! The wheel scrolls a long note, including over wide display formulas.
|
|
use egui::{Context, RawInput};
|
|
use notescraft_engine::Session;
|
|
use notescraft_ui_egui::app::NotesApp;
|
|
use std::sync::atomic::{AtomicU64, Ordering};
|
|
|
|
static NEXT: AtomicU64 = AtomicU64::new(0);
|
|
|
|
const WIDE: &str = r"$$\sum_{k=0}^{n}ar^{k}=a\cdot\frac{1-r^{n+1}}{1-r},\qquad \sum_{k=0}^{\infty}ar^{k}=\frac{a}{1-r},\qquad \sum_{k=1}^{n}k^3=\left(\frac{n(n+1)}{2}\right)^2,\qquad \sum_{k=1}^{n}k^2=\frac{n(n+1)(2n+1)}{6}$$";
|
|
|
|
fn first_heading_y(app: &mut NotesApp, ctx: &Context, wheel: Option<egui::Pos2>) -> Option<f32> {
|
|
let mut found = None;
|
|
for frame in 0..4_u32 {
|
|
let mut events = vec![egui::Event::PointerMoved(wheel.unwrap_or(egui::pos2(700.0, 450.0)))];
|
|
if frame == 2 && wheel.is_some() {
|
|
events.push(egui::Event::MouseWheel {
|
|
unit: egui::MouseWheelUnit::Point,
|
|
delta: egui::vec2(0.0, -200.0),
|
|
phase: egui::TouchPhase::Move,
|
|
modifiers: egui::Modifiers::NONE,
|
|
});
|
|
}
|
|
let mut out = ctx.run_ui(
|
|
RawInput {
|
|
screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1440.0, 900.0))),
|
|
time: Some(f64::from(u32::try_from(NEXT.fetch_add(1, Ordering::Relaxed)).unwrap_or(0))),
|
|
events,
|
|
..Default::default()
|
|
},
|
|
|ui| app.ui(ui.ctx()),
|
|
);
|
|
out.textures_delta.clear();
|
|
found = out.shapes.iter().find_map(|shape| match &shape.shape {
|
|
egui::Shape::Text(text) if text.galley.text() == "Top heading" => Some(text.pos.y),
|
|
_ => None,
|
|
});
|
|
}
|
|
found
|
|
}
|
|
|
|
#[test]
|
|
fn wheel_scrolls_a_note_over_text_and_over_wide_formulas() {
|
|
for (name, body) in [("text", "plain paragraph\n\n".repeat(60)), ("math", format!("{WIDE}\n\n").repeat(30))] {
|
|
let root = std::env::temp_dir().join(format!("notescraft-scroll-{}-{name}", std::process::id()));
|
|
std::fs::create_dir_all(&root).expect("root");
|
|
std::fs::write(root.join("long.md"), format!("# Top heading\n\n{body}")).expect("note");
|
|
let mut session = Session::open(&root).expect("session");
|
|
session.use_settings_dir(root.join("config"));
|
|
let mut app = NotesApp::new(session, notescraft_themes::builtin("catppuccin-mocha").expect("theme"));
|
|
app.open_note("long.md");
|
|
let ctx = Context::default();
|
|
let before = first_heading_y(&mut app, &ctx, None);
|
|
let mut moved = false;
|
|
for (x, y) in [(400.0, 300.0), (600.0, 400.0), (700.0, 520.0), (800.0, 640.0), (900.0, 300.0)] {
|
|
let after = first_heading_y(&mut app, &ctx, Some(egui::pos2(x, y)));
|
|
moved |= before.zip(after).is_none_or(|(b, a)| (b - a).abs() > 20.0);
|
|
}
|
|
assert!(before.is_some() && moved, "{name}: wheel did not move the note ({before:?})");
|
|
}
|
|
}
|