mirror of
https://github.com/storytold/photocraft.git
synced 2026-11-10 10:10:34 -06:00
fix(navigator): zoom the document with the mouse wheel over the preview (#2724)
* fix(navigator): zoom with wheel over the preview (#2716) * rustfmt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
Brandon Thomas
parent
cfe031f2a6
commit
a28d786638
@@ -1627,6 +1627,20 @@ fn navigator(app: &mut PhotocraftApp, ui: &mut egui::Ui) {
|
||||
app.ui.views[idx].center = [d.x.clamp(0.0, size.width as f32), d.y.clamp(0.0, size.height as f32)];
|
||||
app.ui.views[idx].fit_pending = false;
|
||||
}
|
||||
// The Navigator has its own zoom target: an unmodified wheel over the preview
|
||||
// should zoom even when the document canvas is configured to scroll on wheel.
|
||||
// Use the canvas wheel classifier to honour one ×1.1 step per notch without
|
||||
// applying egui's smoothed wheel tail a second time.
|
||||
if resp.hovered()
|
||||
&& let Some(crate::wheel_nav::Wheel::Zoom(factor)) = crate::wheel_nav::read(&ctx, true)
|
||||
{
|
||||
let view = &mut app.ui.views[idx];
|
||||
let next = crate::zoom_levels::clamp(view.zoom * factor, view.doc_size);
|
||||
if next != view.zoom {
|
||||
view.zoom = next;
|
||||
view.fit_pending = false;
|
||||
}
|
||||
}
|
||||
// Visible-area rectangle.
|
||||
let v = app.ui.views[idx].clone();
|
||||
let canvas = app.last_canvas_rect;
|
||||
@@ -1660,6 +1674,43 @@ fn navigator(app: &mut PhotocraftApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod navigator_wheel_tests {
|
||||
use super::*;
|
||||
use egui::{Event, Modifiers, MouseWheelUnit, RawInput, TouchPhase};
|
||||
|
||||
fn frame(app: &mut PhotocraftApp, ctx: &egui::Context, pointer: Pos2, wheel: f32) {
|
||||
let mut events = vec![Event::PointerMoved(pointer)];
|
||||
if wheel != 0.0 {
|
||||
events.push(Event::MouseWheel { unit: MouseWheelUnit::Line, delta: vec2(0.0, wheel), phase: TouchPhase::Move, modifiers: Modifiers::NONE });
|
||||
}
|
||||
let mut out = ctx
|
||||
.run_ui(RawInput { screen_rect: Some(Rect::from_min_size(Pos2::ZERO, vec2(430.0, 460.0))), events, ..Default::default() }, |ui| navigator(app, ui));
|
||||
out.textures_delta.clear();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn navigator_wheel_changes_zoom_only_when_over_preview() {
|
||||
let mut app = PhotocraftApp::new(photocraft_engine::Session::new(), crate::Services::default());
|
||||
app.run("file.new", json!({"width": 200, "height": 100})).unwrap();
|
||||
app.sync_views();
|
||||
app.ui.views[0].zoom = 1.0;
|
||||
app.ui.views[0].fit_pending = false;
|
||||
let ctx = egui::Context::default();
|
||||
PhotocraftApp::setup_context(&ctx, crate::theme::ThemeKind::ALL[0]);
|
||||
crate::wheel_nav::configure(&ctx);
|
||||
frame(&mut app, &ctx, pos2(50.0, 55.0), 0.0);
|
||||
let center = app.ui.views[0].center;
|
||||
frame(&mut app, &ctx, pos2(50.0, 55.0), 1.0);
|
||||
assert!((app.ui.views[0].zoom - 1.1).abs() < 1e-4, "one wheel notch zooms once");
|
||||
assert_eq!(app.ui.views[0].center, center, "Navigator wheel must not pan");
|
||||
frame(&mut app, &ctx, pos2(50.0, 55.0), -1.0);
|
||||
assert!((app.ui.views[0].zoom - 1.0).abs() < 1e-4);
|
||||
frame(&mut app, &ctx, pos2(50.0, 400.0), 1.0);
|
||||
assert!((app.ui.views[0].zoom - 1.0).abs() < 1e-4, "wheel outside preview leaves zoom unchanged");
|
||||
}
|
||||
}
|
||||
|
||||
fn empty(ui: &mut egui::Ui, s: &str) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
ui.add_space(6.0);
|
||||
|
||||
Reference in New Issue
Block a user