Canvas: a General option makes Cmd/Ctrl-wheel scroll the canvas sideways

Squashed from #5023 onto main.
This commit is contained in:
dotCooCoo
2026-11-08 23:50:31 +07:00
committed by bflatastic
parent 0d1a8b6ffa
commit a33d6a6ec8
37 changed files with 472 additions and 14 deletions
+1
View File
@@ -150,6 +150,7 @@ pub const PREF_SPECS: &[PrefSpec] = &[
p!("scaleCorners", "General", "Options", "Scale Corners", bool),
p!("scaleStrokes", "General", "Options", "Scale Strokes & Effects", bool),
p!("zoomWithMouseWheel", "General", "Options", "Zoom with Mouse Wheel", bool),
p!("ctrlWheelScrollsSideways", "General", "Options", "Scroll Sideways with Cmd/Ctrl + Wheel", bool),
p!("scrubNumericFields", "General", "Options", "Scrub Numeric Fields by Dragging", bool),
p!("trackpadRotateView", "General", "Options", "Trackpad Gesture to Rotate View", bool),
p!("holdToolKeys", "General", "Options", "Hold a Tool Shortcut to Use the Tool Temporarily", bool),
+3
View File
@@ -54,6 +54,8 @@ pub struct Prefs {
/// Scale Strokes & Effects.
pub scale_strokes: bool,
pub zoom_with_mouse_wheel: bool,
/// While Zoom with Mouse Wheel is off, Cmd/Ctrl-wheel scrolls sideways instead of zooming.
pub ctrl_wheel_scrolls_sideways: bool,
/// A horizontal drag on a numeric field or its label steps its value (#400).
pub scrub_numeric_fields: bool,
/// A two-finger rotation on a Mac trackpad turns the view about the pointer once it reaches 5°.
@@ -367,6 +369,7 @@ impl Default for Prefs {
scale_corners: false,
scale_strokes: false,
zoom_with_mouse_wheel: false,
ctrl_wheel_scrolls_sideways: true,
scrub_numeric_fields: true,
trackpad_rotate_view: true,
hold_tool_keys: true,
+14
View File
@@ -2511,6 +2511,20 @@ fn a_straight_segment_dragged_by_direct_selection_lands_on_a_ruler_guide() {
}
}
/// General › Scroll Sideways with Cmd/Ctrl + Wheel starts on: in a new session, in a preferences
/// file saved before the option existed and after a reset.
#[test]
fn scroll_sideways_with_cmd_wheel_is_on_by_default() {
assert!(Prefs::default().ctrl_wheel_scrolls_sideways);
let old: Prefs = serde_json::from_value(json!({"zoomWithMouseWheel": false})).unwrap();
assert!(old.ctrl_wheel_scrolls_sideways);
let mut s = Session::new();
s.execute("prefs.set", &json!({"key": "ctrlWheelScrollsSideways", "value": false})).unwrap();
assert!(!s.prefs.ctrl_wheel_scrolls_sideways);
s.execute("prefs.reset", &json!({})).unwrap();
assert!(s.prefs.ctrl_wheel_scrolls_sideways);
}
/// The Transform panel menu's choice starts as `default` (the panels follow General › Transform
/// Pattern Tiles): in a new session, in a preferences file saved before the choice existed and
/// after a reset; `prefs.set` takes it and the three menu choices, and nothing else.
+8 -2
View File
@@ -206,8 +206,14 @@ fn wheel_view(
let turn_id = egui::Id::unique("canvas-wheel-turn");
let turn_before: WheelTurn = ui.data(|d| d.get_temp(turn_id)).unwrap_or_default();
let mut turn = turn_before;
let (pointer, m, space, (factor, scroll)) =
ui.input(|i| (i.pointer.clone(), i.modifiers, i.key_down(egui::Key::Space), wheel(i, wheel_zooms, animate, line, rect.height(), &mut turn)));
let (pointer, m, space, (factor, scroll)) = ui.input(|i| {
(
i.pointer.clone(),
i.modifiers,
i.key_down(egui::Key::Space),
wheel(i, &app.session.prefs, wheel_zooms, animate, line, rect.height(), &mut turn),
)
});
if turn != turn_before {
ui.data_mut(|d| d.insert_temp(turn_id, turn));
}
+288 -2
View File
@@ -4306,7 +4306,8 @@ fn show_hidden_characters_releases_the_text_nodes_of_a_closed_document() {
}
/// General › Zoom with Mouse Wheel (#394), through the control channel's `ui.wheel`: off,
/// the wheel scrolls and Cmd-wheel zooms; on, the wheel zooms about the pointer, Shift-wheel
/// the wheel scrolls and Cmd-wheel scrolls sideways (Scroll Sideways with Cmd/Ctrl + Wheel is on
/// by default); on, the wheel zooms about the pointer, Shift-wheel
/// scrolls up and down and Cmd/Ctrl-wheel sideways. Alt-wheel (Option on the Mac) and a
/// trackpad pinch zoom about the pointer either way.
#[test]
@@ -4348,7 +4349,9 @@ fn zoom_with_mouse_wheel_preference() {
let zooms_in = |(zoom, _, moved): (f64, _, f64)| zoom > 1.01 && moved < 1e-6;
let (zoom, scroll, _) = turn(&mut app, "");
assert!((zoom - 1.0).abs() < 1e-9 && scroll.x == 0.0 && scroll.y < -1.0, "off: the wheel scrolls up ({zoom}, {scroll:?})");
assert!(zooms_in(turn(&mut app, "cmd")), "off: Cmd-wheel zooms in about the pointer");
// General › Scroll Sideways with Cmd/Ctrl + Wheel is on by default.
let (zoom, scroll, _) = turn(&mut app, "cmd");
assert!((zoom - 1.0).abs() < 1e-9 && scroll.x < -1.0 && scroll.y == 0.0, "off: Cmd-wheel scrolls sideways ({zoom}, {scroll:?})");
assert!(zooms_in(turn(&mut app, "alt")), "off: Alt-wheel zooms in about the pointer");
assert!(zooms_in(turn(&mut app, "pinch")), "off: a pinch zooms in about the pointer");
app.session.execute("prefs.set", &json!({"key": "zoomWithMouseWheel", "value": true})).unwrap();
@@ -4361,6 +4364,289 @@ fn zoom_with_mouse_wheel_preference() {
assert!((zoom - 1.0).abs() < 1e-9 && scroll.x < -1.0 && scroll.y == 0.0, "on: Cmd-wheel scrolls sideways ({zoom}, {scroll:?})");
}
/// General › Scroll Sideways with Cmd/Ctrl + Wheel (on by default), through the control channel's
/// `ui.wheel`: with Zoom with Mouse Wheel off, Cmd/Ctrl-wheel zooms about the pointer while the
/// option is off and scrolls sideways while it is on, and a trackpad pinch, two fingers spread on a touch
/// screen, Alt + Cmd/Ctrl-wheel and Alt-wheel still zoom. A Cmd/Ctrl-wheel notch with a plain
/// one right after it scrolls two notches in all, and a trackpad gesture during which Cmd/Ctrl
/// is pressed and released scrolls sideways until the gesture ends, while an Alt gesture that
/// pauses past egui's scroll timeout no longer holds Alt for the next move. With Zoom with
/// Mouse Wheel also on, Cmd/Ctrl-wheel scrolls sideways and the wheel zooms.
#[test]
fn cmd_wheel_scrolls_sideways_preference() {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 400, "height": 300})).unwrap();
let ctx = egui::Context::default();
// A canvas frame through the host's input hook (it feeds the control channel's input).
let run = |app: &mut VectorcraftApp| {
let mut raw = egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(Pos2::ZERO, vec2(800.0, 600.0))), ..Default::default() };
app.raw_input_hook(&ctx, &mut raw);
let mut out = ctx.run_ui(raw, |ui| show(app, ui));
out.textures_delta.clear();
};
run(&mut app);
let rect = app.canvas_rect.unwrap();
let at = rect.center() + vec2(60.0, 40.0);
// One notch up at `at` with `mods` held, or a pinch: → (zoom ratio, scroll in points, how
// far the point under `at` moved).
let turn = |app: &mut VectorcraftApp, mods: &str| {
let before = *app.view().unwrap();
if mods == "pinch" {
app.synthetic.extend([egui::Event::PointerMoved(at), egui::Event::Zoom(1.25)]);
} else {
let mut p = json!({"x": at.x, "y": at.y, "dy": 1});
for m in mods.split('+').filter(|m| !m.is_empty()) {
p[m] = json!(true);
}
crate::tests_synthetic::control(app, &ctx, "ui.wheel", p);
}
// egui spreads a notch over a few frames.
for _ in 0..40 {
run(app);
}
let after = *app.view().unwrap();
let moved = Xf::new(rect, &after).to_doc(at).distance(Xf::new(rect, &before).to_doc(at));
(after.zoom / before.zoom, (after.center - before.center) * after.zoom, moved)
};
let zooms_in = |(zoom, _, moved): (f64, _, f64)| zoom > 1.01 && moved < 1e-6;
assert!(app.session.prefs.ctrl_wheel_scrolls_sideways, "the option is on by default");
app.session.execute("prefs.set", &json!({"key": "ctrlWheelScrollsSideways", "value": false})).unwrap();
assert!(zooms_in(turn(&mut app, "cmd")), "off: Cmd-wheel zooms in about the pointer");
let (zoom, scroll, _) = turn(&mut app, "shift");
assert!((zoom - 1.0).abs() < 1e-9 && scroll.x < -1.0 && scroll.y == 0.0, "off: Shift-wheel scrolls sideways ({zoom}, {scroll:?})");
app.session.execute("prefs.set", &json!({"key": "ctrlWheelScrollsSideways", "value": true})).unwrap();
// A notch scrolls one wheel line.
let line = f64::from(ctx.options(|o| o.input_options.line_scroll_speed));
let (zoom, scroll, _) = turn(&mut app, "cmd");
assert!(
(zoom - 1.0).abs() < 1e-9 && (scroll.x + line).abs() < 0.5 && scroll.y == 0.0,
"on: Cmd-wheel scrolls sideways by a notch ({zoom}, {scroll:?})"
);
assert!(zooms_in(turn(&mut app, "pinch")), "on: a pinch right after it zooms in about the pointer");
// Two fingers spread on a touch screen, with no wheel turn since the Cmd-wheel one.
let before = app.view().unwrap().zoom;
let touch = |n: u64, phase, pos| egui::Event::Touch { device_id: egui::TouchDeviceId(1), id: egui::TouchId(n), phase, pos, force: None };
let fingers = |phase, d: f32| vec![touch(1, phase, at - vec2(40.0 + d, 0.0)), touch(2, phase, at + vec2(40.0 + d, 0.0))];
frame(&mut app, &ctx, fingers(egui::TouchPhase::Start, 0.0));
for k in 1..=3 {
frame(&mut app, &ctx, fingers(egui::TouchPhase::Move, 10.0 * k as f32));
}
frame(&mut app, &ctx, fingers(egui::TouchPhase::End, 30.0));
let zoom = app.view().unwrap().zoom / before;
assert!(zoom > 1.01, "on: fingers spread on a touch screen zoom in ({zoom})");
assert!(zooms_in(turn(&mut app, "alt+cmd")), "on: Alt + Cmd-wheel zooms in about the pointer");
assert!(zooms_in(turn(&mut app, "alt")), "on: so does Alt-wheel");
let (zoom, scroll, _) = turn(&mut app, "");
assert!((zoom - 1.0).abs() < 1e-9 && scroll.x == 0.0 && scroll.y < -1.0, "on: the wheel scrolls up ({zoom}, {scroll:?})");
let (zoom, scroll, _) = turn(&mut app, "shift");
assert!((zoom - 1.0).abs() < 1e-9 && scroll.x < -1.0 && scroll.y == 0.0, "on: Shift-wheel scrolls sideways ({zoom}, {scroll:?})");
// A Cmd-wheel notch with a plain one right after it, before egui has spread the first: they
// scroll two notches in all, sideways and up.
let before = *app.view().unwrap();
crate::tests_synthetic::control(&mut app, &ctx, "ui.wheel", json!({"x": at.x, "y": at.y, "dy": 1, "cmd": true}));
crate::tests_synthetic::control(&mut app, &ctx, "ui.wheel", json!({"x": at.x, "y": at.y, "dy": 1}));
for _ in 0..40 {
run(&mut app);
}
let after = *app.view().unwrap();
let scroll = (after.center - before.center) * after.zoom;
assert!(
scroll.x < -1.0 && scroll.y < -1.0 && (scroll.x + scroll.y + 2.0 * line).abs() < 0.5,
"on: a Cmd-wheel notch and a plain one right after it scroll two notches in all ({scroll:?})"
);
// A pinch while egui still spreads a Cmd-wheel notch zooms by the pinch alone, and the
// canvas scrolls sideways by one notch; the pinch magnifies the part scrolled before it.
let before = *app.view().unwrap();
let p = Xf::new(rect, &before).to_doc(at);
crate::tests_synthetic::control(&mut app, &ctx, "ui.wheel", json!({"x": at.x, "y": at.y, "dy": 1, "cmd": true}));
app.synthetic.extend([egui::Event::PointerMoved(at), egui::Event::Zoom(1.25)]);
for _ in 0..40 {
run(&mut app);
}
let after = *app.view().unwrap();
let (zoom, moved) = (after.zoom / before.zoom, Xf::new(rect, &after).to_screen(p) - at);
let notch = line as f32;
assert!(
(zoom - 1.25).abs() < 1e-6 && moved.x > notch - 0.5 && moved.x < 1.25 * notch + 0.5 && moved.y.abs() < 1e-3,
"on: a pinch during a Cmd-wheel notch zooms by the pinch, and the notch scrolls sideways ({zoom}, {moved:?})"
);
// A trackpad gesture starts with no modifier, and Cmd is pressed and released during it:
// egui keeps Cmd in its wheel state until the gesture ends, and the canvas keeps scrolling
// sideways until then.
let before = *app.view().unwrap();
let swipe = |phase, modifiers| egui::Event::MouseWheel {
unit: egui::MouseWheelUnit::Point,
delta: vec2(0.0, 6.0),
phase,
modifiers,
source: egui::MouseWheelSource::Unknown,
};
app.synthetic.extend([
egui::Event::PointerMoved(at),
swipe(egui::TouchPhase::Start, egui::Modifiers::NONE),
swipe(egui::TouchPhase::Move, egui::Modifiers::COMMAND),
swipe(egui::TouchPhase::Move, egui::Modifiers::NONE),
swipe(egui::TouchPhase::End, egui::Modifiers::NONE),
]);
for _ in 0..40 {
run(&mut app);
}
let after = *app.view().unwrap();
let scroll = (after.center - before.center) * after.zoom;
assert!(
(after.zoom / before.zoom - 1.0).abs() < 1e-9 && (scroll.x + 12.0).abs() < 0.01 && scroll.y == 0.0,
"on: a trackpad gesture scrolls sideways to its end after Cmd is let go ({}, {scroll:?})",
after.zoom / before.zoom
);
// An Alt-wheel gesture pauses past egui's scroll timeout with no frame in between: egui
// ends it before the next event, so a move with Cmd alone scrolls sideways.
// Frames at the given times, with the events in the frame's own input (the host's input
// hook hands synthetic events out over several frames).
let run_at = |app: &mut VectorcraftApp, time: f64, events: Vec<egui::Event>| {
let raw = egui::RawInput {
screen_rect: Some(egui::Rect::from_min_size(Pos2::ZERO, vec2(800.0, 600.0))),
time: Some(time),
events,
..Default::default()
};
let mut out = ctx.run_ui(raw, |ui| show(app, ui));
out.textures_delta.clear();
};
// The Alt part rests the fingers without moving, so only the Cmd move below acts.
let rest = |phase| egui::Event::MouseWheel {
unit: egui::MouseWheelUnit::Point,
delta: Vec2::ZERO,
phase,
modifiers: egui::Modifiers::ALT,
source: egui::MouseWheelSource::Unknown,
};
let t = ctx.input(|i| i.time) + 1.0;
run_at(&mut app, t, vec![egui::Event::PointerMoved(at), rest(egui::TouchPhase::Start), rest(egui::TouchPhase::Move)]);
let before = *app.view().unwrap();
run_at(&mut app, t + 2.0, vec![swipe(egui::TouchPhase::Move, egui::Modifiers::COMMAND)]);
for k in 1..=40 {
run_at(&mut app, t + 2.0 + f64::from(k) / 60.0, vec![]);
}
let after = *app.view().unwrap();
let scroll = (after.center - before.center) * after.zoom;
assert!(
(after.zoom / before.zoom - 1.0).abs() < 1e-9 && (scroll.x + 6.0).abs() < 0.01 && scroll.y == 0.0,
"on: after egui's timeout, a Cmd move scrolls sideways ({}, {scroll:?})",
after.zoom / before.zoom
);
app.session.execute("prefs.set", &json!({"key": "zoomWithMouseWheel", "value": true})).unwrap();
let (zoom, scroll, _) = turn(&mut app, "cmd");
assert!(
(zoom - 1.0).abs() < 1e-9 && scroll.x < -1.0 && scroll.y == 0.0,
"with Zoom with Mouse Wheel: Cmd-wheel scrolls sideways ({zoom}, {scroll:?})"
);
assert!(zooms_in(turn(&mut app, "")), "with Zoom with Mouse Wheel: the wheel zooms in about the pointer");
}
/// With Scroll Sideways with Cmd/Ctrl + Wheel on and Animated Zoom off, Alt + Cmd-wheel zooms
/// about the pointer by egui's Cmd-wheel zoom, as Cmd-wheel does with the option off, and
/// Cmd-wheel alone scrolls sideways.
#[test]
fn cmd_wheel_sideways_alt_cmd_zooms_without_animated_zoom() {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 400, "height": 300})).unwrap();
for (key, value) in [("ctrlWheelScrollsSideways", true), ("zoomWithMouseWheel", false), ("animatedZoom", false)] {
app.session.execute("prefs.set", &json!({"key": key, "value": value})).unwrap();
}
let ctx = egui::Context::default();
let run = |app: &mut VectorcraftApp| {
let mut raw = egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(Pos2::ZERO, vec2(800.0, 600.0))), ..Default::default() };
app.raw_input_hook(&ctx, &mut raw);
let mut out = ctx.run_ui(raw, |ui| show(app, ui));
out.textures_delta.clear();
};
run(&mut app);
let rect = app.canvas_rect.unwrap();
let at = rect.center() + vec2(60.0, 40.0);
let before = *app.view().unwrap();
crate::tests_synthetic::control(&mut app, &ctx, "ui.wheel", json!({"x": at.x, "y": at.y, "dy": 1, "alt": true, "cmd": true}));
for _ in 0..40 {
run(&mut app);
}
let after = *app.view().unwrap();
let expected = ctx.options(|o| f64::from(o.input_options.line_scroll_speed * o.input_options.scroll_zoom_speed).exp());
let zoom = after.zoom / before.zoom;
assert!((zoom - expected).abs() < 1e-3, "Alt + Cmd-wheel zooms in by one notch ({zoom}, expected {expected})");
assert!(Xf::new(rect, &after).to_doc(at).distance(Xf::new(rect, &before).to_doc(at)) < 1e-6, "Alt + Cmd-wheel zooms about the pointer");
let before = after;
crate::tests_synthetic::control(&mut app, &ctx, "ui.wheel", json!({"x": at.x, "y": at.y, "dy": 1, "cmd": true}));
for _ in 0..40 {
run(&mut app);
}
let after = *app.view().unwrap();
let scroll = (after.center - before.center) * after.zoom;
let line = f64::from(ctx.options(|o| o.input_options.line_scroll_speed));
assert!((after.zoom / before.zoom - 1.0).abs() < 1e-9, "Cmd-wheel does not zoom");
assert!((scroll.x + line).abs() < 0.5 && scroll.y == 0.0, "Cmd-wheel scrolls sideways ({scroll:?})");
}
/// With Zoom with Mouse Wheel off, a trackpad gesture that starts with Alt keeps zooming about the
/// pointer until it ends, also after Alt is let go, as egui keeps a modifier held during a gesture,
/// with Animated Zoom on and off. A gesture that gains Alt partway zooms from then on.
#[test]
fn alt_wheel_gesture_keeps_zooming_after_alt_is_let_go() {
for animate in [true, false] {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 400, "height": 300})).unwrap();
for (key, value) in [("zoomWithMouseWheel", false), ("animatedZoom", animate)] {
app.session.execute("prefs.set", &json!({"key": key, "value": value})).unwrap();
}
let ctx = egui::Context::default();
let run = |app: &mut VectorcraftApp| {
let mut raw = egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(Pos2::ZERO, vec2(800.0, 600.0))), ..Default::default() };
app.raw_input_hook(&ctx, &mut raw);
let mut out = ctx.run_ui(raw, |ui| show(app, ui));
out.textures_delta.clear();
};
run(&mut app);
let rect = app.canvas_rect.unwrap();
let at = rect.center() + vec2(60.0, 40.0);
let swipe = |phase, modifiers| egui::Event::MouseWheel {
unit: egui::MouseWheelUnit::Point,
delta: vec2(0.0, 6.0),
phase,
modifiers,
source: egui::MouseWheelSource::Unknown,
};
// One gesture with the given modifiers on its Start and its two Moves → (zoom ratio, how far
// the point under `at` moved).
let gesture = |app: &mut VectorcraftApp, mods: [egui::Modifiers; 3]| {
let before = *app.view().unwrap();
app.synthetic.extend([
egui::Event::PointerMoved(at),
swipe(egui::TouchPhase::Start, mods[0]),
swipe(egui::TouchPhase::Move, mods[1]),
swipe(egui::TouchPhase::Move, mods[2]),
swipe(egui::TouchPhase::End, egui::Modifiers::NONE),
]);
for _ in 0..40 {
run(app);
}
let after = *app.view().unwrap();
(after.zoom / before.zoom, Xf::new(rect, &after).to_doc(at).distance(Xf::new(rect, &before).to_doc(at)))
};
let alt = egui::Modifiers::ALT;
let (held, _) = gesture(&mut app, [alt, alt, alt]);
assert!(held > 1.01, "animate {animate}: an Alt gesture zooms in ({held})");
let (zoom, moved) = gesture(&mut app, [alt, alt, egui::Modifiers::NONE]);
assert!(
(zoom - held).abs() < 1e-9 && moved < 1e-6,
"animate {animate}: a move without Alt keeps the gesture zooming about the pointer ({zoom}, expected {held}; moved {moved})"
);
let (zoom, moved) = gesture(&mut app, [egui::Modifiers::NONE, alt, egui::Modifiers::NONE]);
assert!(
(zoom - held).abs() < 1e-9 && moved < 1e-6,
"animate {animate}: Alt pressed partway zooms the rest of the gesture about the pointer ({zoom}, expected {held}; moved {moved})"
);
}
}
/// #888: with Zoom with Mouse Wheel, a wheel notch's zoom glides in over a few frames, as a
/// scroll does, instead of jumping on the frame it arrives; it ends at the same zoom.
#[test]
+84 -9
View File
@@ -52,8 +52,19 @@ const WHEEL_GLIDE: f64 = 0.05;
/// What the wheel did across frames ([`wheel`]).
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub(super) struct WheelTurn {
/// The last wheel turn was an Alt-wheel one.
/// The last wheel turn was an Alt-wheel one: `held` had Alt without Cmd/Ctrl at its last Start
/// or Move.
alt: bool,
/// The modifiers egui's wheel state holds, followed while Zoom with Mouse Wheel is off: each
/// wheel event's own, or, through a trackpad gesture, all those held since it began; none
/// while the wheel is idle.
held: egui::Modifiers,
/// A trackpad gesture is under way: egui has seen its Start phase and has not yet seen its End
/// or Cancel phase.
gesture: bool,
/// When the last wheel event came (`InputState::time`), and whether a trackpad sent it.
last: f64,
trackpad: bool,
/// The zoom (natural log) wheel notches still have to glide in.
pub(super) glide: f64,
}
@@ -342,13 +353,22 @@ struct ThumbDrag {
/// What the wheel, a pinch and a two-finger drag on a touch screen did over the canvas this frame:
/// a zoom factor (about the pointer) and a scroll (screen points the content moves). The wheel scrolls, Cmd- and Alt-wheel (Option
/// on the Mac) zoom. With General › Zoom with Mouse Wheel (`wheel_zooms`) the wheel and Alt-wheel
/// zoom, Shift-wheel scrolls up and down and Cmd/Ctrl-wheel sideways. `line` and `page`: points
/// on the Mac) zoom; with General › Scroll Sideways with Cmd/Ctrl + Wheel, Cmd/Ctrl-wheel scrolls
/// sideways instead, and Alt + Cmd/Ctrl-wheel still zooms. With General › Zoom with Mouse Wheel the
/// wheel and Alt-wheel zoom, Shift-wheel scrolls up and down and Cmd/Ctrl-wheel sideways. `line` and `page`: points
/// per wheel line and page. `turn`: kept by the caller across frames. With Performance › Animated
/// Zoom (`animate`) a mouse wheel's notches zoom in a glide over a few frames, as scrolling does
/// (#888); off, each notch zooms on the frame it arrives (#4283). A trackpad's fine steps zoom at
/// once either way.
pub(super) fn wheel(i: &egui::InputState, wheel_zooms: bool, animate: bool, line: f32, page: f32, turn: &mut WheelTurn) -> (f64, egui::Vec2) {
pub(super) fn wheel(
i: &egui::InputState,
prefs: &vectorcraft_engine::Prefs,
wheel_zooms: bool,
animate: bool,
line: f32,
page: f32,
turn: &mut WheelTurn,
) -> (f64, egui::Vec2) {
// Fingers on a touch screen pan the content with them (a trackpad sends scrolls instead).
let pan = i.multi_touch().map_or(egui::Vec2::ZERO, |t| t.translation_delta);
// A wheel event's motion in points.
@@ -360,17 +380,72 @@ pub(super) fn wheel(i: &egui::InputState, wheel_zooms: bool, animate: bool, line
if !wheel_zooms {
// egui makes Cmd-wheel (and a pinch) its zoom and the rest a scroll it spreads over a few
// frames: the rest of an Alt-wheel turn zooms too, however soon Alt is let go.
if let Some(m) = i.events.iter().rev().find_map(|e| if let egui::Event::MouseWheel { modifiers, .. } = e { Some(modifiers) } else { None }) {
turn.alt = m.alt && !m.command;
// Each wheel event changes `turn.held` and `turn.gesture` as `WheelState::on_wheel_event`
// changes egui's wheel modifiers and status. Both are cleared while egui's wheel is idle.
// `turn.alt` follows `turn.held` after each Start or Move, so a trackpad gesture that held
// Alt keeps zooming until it ends, also after Alt is let go.
for e in &i.events {
if let egui::Event::MouseWheel { phase, modifiers, source, .. } = e {
// A wheel event that comes after egui's scroll timeout ends the turn first, as
// `on_wheel_event` does (1 s for fingers resting on a trackpad mid-gesture, else
// 0.15 s), also when no frame ran in between.
let timeout = if turn.gesture && turn.trackpad { 1.0 } else { 0.150 };
if i.time - turn.last > timeout {
turn.gesture = false;
turn.held = egui::Modifiers::NONE;
}
turn.last = i.time;
turn.trackpad = *source == egui::MouseWheelSource::Trackpad;
match phase {
egui::TouchPhase::Start => {
turn.gesture = true;
turn.held = *modifiers;
turn.alt = turn.held.alt && !turn.held.command;
}
egui::TouchPhase::Move => {
if turn.gesture {
turn.held |= *modifiers;
} else {
turn.held = *modifiers;
}
turn.alt = turn.held.alt && !turn.held.command;
}
egui::TouchPhase::End | egui::TouchPhase::Cancel => {
turn.gesture = false;
turn.held = egui::Modifiers::NONE;
}
}
}
}
if !i.is_scrolling() {
turn.gesture = false;
turn.held = egui::Modifiers::NONE;
}
let (mut zoom, mut scroll) = (f64::from(i.zoom_delta()), i.smooth_scroll_delta);
// Scroll Sideways with Cmd/Ctrl + Wheel: while egui's wheel state holds Cmd/Ctrl without
// Alt, egui's zoom, less the pinches', is `exp(points × scroll_zoom_speed)`, at egui's
// default speed, which the app keeps. The canvas scrolls sideways by those points instead.
// A trackpad or web pinch still zooms. With fingers on a touch screen, egui's zoom is the
// fingers' alone, and the canvas leaves it as it is.
if prefs.ctrl_wheel_scrolls_sideways && turn.held.command && !turn.held.alt && i.multi_touch().is_none() {
let pinch: f64 = i.events.iter().filter_map(|e| if let egui::Event::Zoom(f) = e { Some(f64::from(*f)) } else { None }).product();
let wheel_zoom = zoom / pinch;
if wheel_zoom.is_finite() && wheel_zoom > 0.0 {
scroll.x += (wheel_zoom.ln() / f64::from(egui::InputOptions::default().scroll_zoom_speed)) as f32;
zoom = pinch;
}
}
let (zoom, scroll) = (f64::from(i.zoom_delta()), i.smooth_scroll_delta);
if turn.alt && !animate {
// Without Animated Zoom, Alt-wheel zooms by the wheel events themselves, on the frame
// they arrive; the rest of egui's spread scroll is dropped.
// they arrive; the rest of egui's spread scroll is dropped. Only Move events count, as
// `on_wheel_event` moves egui's scroll by Move events alone.
let d: f32 = i
.events
.iter()
.filter_map(|e| if let egui::Event::MouseWheel { unit, delta, .. } = e { Some(points(unit, *delta)) } else { None })
.filter_map(|e| match e {
egui::Event::MouseWheel { unit, delta, phase: egui::TouchPhase::Move, .. } => Some(points(unit, *delta)),
_ => None,
})
.map(|d| d.x + d.y)
.sum();
return (zoom * (f64::from(d) * WHEEL_ZOOM).exp(), pan);
+1
View File
@@ -3710,6 +3710,7 @@ digits Malayalam Малаялам
Zoom to Selection Приближаване до селекцията
Zoom Tool Инструмент „Мащаб“
Zoom with Mouse Wheel Мащабиране с колелцето на мишката
Scroll Sideways with Cmd/Ctrl + Wheel Хоризонтално превъртане с Cmd/Ctrl + колелцето
Scrub Numeric Fields by Dragging Плъзгане на числени полета чрез влачене
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {n} файл в {folder} {note}. Показване на папката на пакета?|{n} файла в {folder} {note}. Показване на папката на пакета?
@plural {n} linked file not found|{n} linked files not found {n} свързан файл не е намерен|{n} свързани файла не са намерени
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3699,6 +3699,7 @@ theme Appearance Izgled
Yards Jardi
Zoom to Selection Zumiraj na odabir
Zoom with Mouse Wheel Zumiraj točkićem miša
Scroll Sideways with Cmd/Ctrl + Wheel Pomjeraj vodoravno uz Cmd/Ctrl + točkić miša
Scrub Numeric Fields by Dragging Mijenjaj numerička polja prevlačenjem
Linux Display Server Linux server prikaza
Print Preview Pregled štampanja
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3728,6 +3728,7 @@ digits Malayalam Malaiàlam
Scribble… Garabateig…
Script / Brush Cal·ligràfica / Pinzell
Scripts Scripts
Scroll Sideways with Cmd/Ctrl + Wheel Desplaça horitzontalment amb Cmd/Ctrl + roda del ratolí
Scrub Numeric Fields by Dragging Canvia els camps numèrics arrossegant
Search Cerca
Search All Cerca a tot
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3744,6 +3744,7 @@ theme Appearance Motiv
Yards Yardy
Zoom to Selection Zvětšit na výběr
Zoom with Mouse Wheel Zvětšovat kolečkem myši
Scroll Sideways with Cmd/Ctrl + Wheel Posouvat vodorovně kolečkem s Cmd/Ctrl
Scrub Numeric Fields by Dragging Měnit číselné hodnoty tažením
Linux Display Server Zobrazovací server Linuxu
Print Preview Náhled tisku
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3472,6 +3472,7 @@ theme Appearance Udseende
Yards Yards
Zoom to Selection Zoom til markering
Zoom with Mouse Wheel Zoom med musehjul
Scroll Sideways with Cmd/Ctrl + Wheel Rul vandret med Cmd/Ctrl + musehjul
Scrub Numeric Fields by Dragging Juster numeriske felter ved at trække
Linux Display Server Linux-visningsserver
Print Preview Udskriftsvisning
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3703,6 +3703,7 @@ effect Points Punkte
Zoom to Selection Auf Auswahl zoomen
Zoom Tool Zoom-Werkzeug
Zoom with Mouse Wheel Mit Mausrad zoomen
Scroll Sideways with Cmd/Ctrl + Wheel Mit Cmd/Ctrl + Mausrad horizontal scrollen
Scrub Numeric Fields by Dragging Zahlenfelder durch Ziehen ändern
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {n} Datei in {folder} {note}. Paketordner anzeigen?|{n} Dateien in {folder} {note}. Paketordner anzeigen?
@plural {n} linked file not found|{n} linked files not found {n} verknüpfte Datei nicht gefunden|{n} verknüpfte Dateien nicht gefunden
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4036,6 +4036,7 @@ digits Malayalam Μαλαγιάλαμ
Zig Zag… Ζιγκ-ζαγκ…
Zoom to Selection Ζουμ στην επιλογή
Zoom with Mouse Wheel Ζουμ με τον τροχό του ποντικιού
Scroll Sideways with Cmd/Ctrl + Wheel Οριζόντια κύλιση με Cmd/Ctrl + τροχό του ποντικιού
Scrub Numeric Fields by Dragging Ρύθμιση αριθμητικών πεδίων με σύρσιμο
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {n} αρχείο στον φάκελο {folder} {note}. Να εμφανιστεί ο φάκελος συσκευασίας;|{n} αρχεία στον φάκελο {folder} {note}. Να εμφανιστεί ο φάκελος συσκευασίας;
@plural {n} linked file not found|{n} linked files not found Δεν βρέθηκε {n} συνδεδεμένο αρχείο|Δεν βρέθηκαν {n} συνδεδεμένα αρχεία
Can't render this file because it contains an unexpected character in line 168 and column 5.
+1
View File
@@ -3793,6 +3793,7 @@ digits Malayalam Malayálam
Zoom to Selection Zoom a la selección
Zoom Tool Herramienta Zoom
Zoom with Mouse Wheel Zoom con la rueda del mouse
Scroll Sideways with Cmd/Ctrl + Wheel Desplazar horizontalmente con Cmd/Ctrl + rueda del mouse
Scrub Numeric Fields by Dragging Ajustar campos numéricos arrastrando
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {n} archivo en {folder} {note}. ¿Mostrar la carpeta del paquete?|{n} archivos en {folder} {note}. ¿Mostrar la carpeta del paquete?
@plural {n} linked file not found|{n} linked files not found No se encontró {n} archivo vinculado|No se encontraron {n} archivos vinculados
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3668,6 +3668,7 @@ theme Appearance Ulkoasu
Yards Jaardit
Zoom to Selection Zoomaa valintaan
Zoom with Mouse Wheel Zoomaa hiiren rullalla
Scroll Sideways with Cmd/Ctrl + Wheel Vieritä vaakasuunnassa Cmd/Ctrl + hiiren rullalla
Scrub Numeric Fields by Dragging Muuta numerokenttiä vetämällä
Linux Display Server Linuxin näyttöpalvelin
Print Preview Tulostuksen esikatselu
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3785,6 +3785,7 @@ digits Malayalam Malayalam
Zoom to Selection Zoom sur la sélection
Zoom Tool Outil Zoom
Zoom with Mouse Wheel Zoom avec la molette de la souris
Scroll Sideways with Cmd/Ctrl + Wheel Défilement horizontal avec Cmd/Ctrl + molette
Scrub Numeric Fields by Dragging Modifier les champs numériques en faisant glisser
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {n} fichier dans {folder} {note}. Afficher le dossier de l’assemblage ?|{n} fichiers dans {folder} {note}. Afficher le dossier de l’assemblage ?
@plural {n} linked file not found|{n} linked files not found {n} fichier lié introuvable|{n} fichiers liés introuvables
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4526,6 +4526,7 @@ mark-style Japanese Japán
Zoom to Selection Nagyítás a kijelölésre
Zoom Tool Nagyító
Zoom with Mouse Wheel Nagyítás egérgörgővel
Scroll Sideways with Cmd/Ctrl + Wheel Vízszintes görgetés Cmd/Ctrl + görgővel
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? Fájlok: {n}, mappa: {folder} {note}. Megnyitod a csomag mappáját?
@plural {n} folder or file couldn't be read|{n} folders or files couldn't be read Nem olvasható mappák vagy fájlok: {n}
@plural {n} folder skipped, such as another app's or the system's folder or a hidden one|{n} folders skipped, such as other apps' and the system's folders and hidden ones Kihagyott mappák: {n} (például más alkalmazások, a rendszer és a rejtett mappák)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3472,6 +3472,7 @@ theme Appearance Tampilan
Yards Yard
Zoom to Selection Zum ke seleksi
Zoom with Mouse Wheel Zum dengan roda mouse
Scroll Sideways with Cmd/Ctrl + Wheel Gulir horizontal dengan Cmd/Ctrl + roda mouse
Scrub Numeric Fields by Dragging Atur nilai kolom numerik dengan menyeret
Linux Display Server Server tampilan Linux
Print Preview Pratinjau cetak
Can't render this file because it contains an unexpected character in line 2260 and column 5.
+1
View File
@@ -3830,6 +3830,7 @@ digits Malayalam Malayalam
Zoom to Selection Zoom sulla selezione
Zoom Tool Strumento Zoom
Zoom with Mouse Wheel Zoom con la rotellina del mouse
Scroll Sideways with Cmd/Ctrl + Wheel Scorrimento orizzontale con Cmd/Ctrl + rotellina
Scrub Numeric Fields by Dragging Regola i campi numerici trascinando
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {n} file in {folder} {note}. Vuoi mostrare la cartella del pacchetto?|{n} file in {folder} {note}. Vuoi mostrare la cartella del pacchetto?
@plural {n} linked file not found|{n} linked files not found File collegati non trovati: {n}|File collegati non trovati: {n}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3408,6 +3408,7 @@ mark-style Japanese 日本式
Zoom Tool ズームツール
Zoom to Selection 選択範囲にズーム
Zoom with Mouse Wheel マウスホイールでズーム
Scroll Sideways with Cmd/Ctrl + Wheel Cmd/Ctrl + ホイールで横スクロール
Scrub Numeric Fields by Dragging ドラッグで数値フィールドを調整
[Default] is protected: New… starts an editable copy. [Default] は変更できません。「新規…」で編集できる複製を作ります。
[Unnamed] [名称未設定]
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3288,6 +3288,7 @@ theme Appearance იერსახე
Yards იარდები
Zoom to Selection მონიშნულის მასშტაბირება
Zoom with Mouse Wheel მაუსის ბორბლით მასშტაბირება
Scroll Sideways with Cmd/Ctrl + Wheel ჰორიზონტალური გადაადგილება Cmd/Ctrl + ბორბლით
Scrub Numeric Fields by Dragging რიცხვითი ველების შეცვლა გადათრევით
Linux Display Server Linux-ის ეკრანის სერვერი
Print Preview ნახვა ამობეჭდვამდე
Can't render this file because it is too large.
+1
View File
@@ -3397,6 +3397,7 @@ mark-style Japanese 일본식
Zoom Tool 확대/축소 도구
Zoom to Selection 선택 항목에 맞춰 확대/축소
Zoom with Mouse Wheel 마우스 휠로 확대/축소
Scroll Sideways with Cmd/Ctrl + Wheel Cmd/Ctrl + 휠로 가로 스크롤
Scrub Numeric Fields by Dragging 드래그로 숫자 필드 조절
[Default] is protected: New… starts an editable copy. [Default]는 보호되어 있습니다. 새로 만들기…를 누르면 편집 가능한 복사본이 만들어집니다.
[Unnamed] [이름 없음]
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3486,6 +3486,7 @@ theme Appearance Vormgeving
Yards Yards
Zoom to Selection Inzoomen op selectie
Zoom with Mouse Wheel Zoomen met muiswiel
Scroll Sideways with Cmd/Ctrl + Wheel Horizontaal scrollen met Cmd/Ctrl + muiswiel
Scrub Numeric Fields by Dragging Numerieke velden aanpassen door te slepen
Linux Display Server Linux-weergaveserver
Print Preview Afdrukvoorbeeld
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3607,6 +3607,7 @@ theme Appearance Wygląd
Yards Jardy
Zoom to Selection Powiększaj do zaznaczenia
Zoom with Mouse Wheel Powiększaj kółkiem myszy
Scroll Sideways with Cmd/Ctrl + Wheel Przewijaj w poziomie kółkiem z Cmd/Ctrl
Scrub Numeric Fields by Dragging Zmieniaj pola liczbowe przeciąganiem
Linux Display Server Serwer wyświetlania Linux
Print Preview Podgląd wydruku
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3115,6 +3115,7 @@ digits Malayalam Malaiala
Zoom Tool Ferramenta Zoom
Zoom to Selection Ampliar para a Seleção
Zoom with Mouse Wheel Zoom com a Roda do Mouse
Scroll Sideways with Cmd/Ctrl + Wheel Rolar na Horizontal com Cmd/Ctrl + Roda
Scrub Numeric Fields by Dragging Ajustar Campos Numéricos Arrastando
[Default] is protected: New… starts an editable copy. [Padrão] é protegido: Novo… inicia uma cópia editável.
[Unnamed] [Sem Nome]
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -3825,6 +3825,7 @@ digits Malayalam Малаялам
Zoom to Selection Масштаб по выделению
Zoom Tool Инструмент «Масштаб»
Zoom with Mouse Wheel Масштабировать колесом мыши
Scroll Sideways with Cmd/Ctrl + Wheel Прокручивать по горизонтали колесом с Cmd/Ctrl
Scrub Numeric Fields by Dragging Изменять числовые поля перетаскиванием
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? Файлов: {n} в {folder} {note}. Показать папку пакета?|Файлов: {n} в {folder} {note}. Показать папку пакета?|Файлов: {n} в {folder} {note}. Показать папку пакета?
@plural {n} linked file not found|{n} linked files not found Не найдено связанных файлов: {n}|Не найдено связанных файлов: {n}|Не найдено связанных файлов: {n}
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3715,6 +3715,7 @@ digits Malayalam Malayalam
Zoom to Selection Zooma till markering
Zoom Tool Zoomverktyg
Zoom with Mouse Wheel Zooma med mushjulet
Scroll Sideways with Cmd/Ctrl + Wheel Rulla horisontellt med Cmd/Ctrl + mushjulet
Scrub Numeric Fields by Dragging Ändra numeriska fält genom att dra
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {n} fil i {folder} {note}. Visa paketmappen?|{n} filer i {folder} {note}. Visa paketmappen?
@plural {n} linked file not found|{n} linked files not found {n} länkad fil hittades inte|{n} länkade filer hittades inte
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -3602,6 +3602,7 @@ digits Malayalam Malayalam
Zoom to Selection Seçimi Yakınlaştır
Zoom Tool Yakınlaştırma Aracı
Zoom with Mouse Wheel Fare Tekerleği ile Yakınlaştırma
Scroll Sideways with Cmd/Ctrl + Wheel Cmd/Ctrl + Tekerlek ile Yatay Kaydırma
Scrub Numeric Fields by Dragging Sayısal Alanları Sürükleyerek Fırçalayın
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {folder} içinde {n} dosya {note}. Paket klasörü gösterilsin mi?
@plural {n} linked file not found|{n} linked files not found {n} bağlantılı dosya bulunamadı
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -3823,6 +3823,7 @@ effect Points Точки
Zoom to Selection Масштаб виділення
Zoom Tool Інструмент «Масштаб»
Zoom with Mouse Wheel Масштабувати колесом миші
Scroll Sideways with Cmd/Ctrl + Wheel Прокручувати по горизонталі колесом із Cmd/Ctrl
Scrub Numeric Fields by Dragging Змінювати числові поля перетягуванням
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? файлів: {n} {folder} {note}. Показати папку пакета?|файлів: {n} {folder} {note}. Показати папку пакета?|файлів: {n} {folder} {note}. Показати папку пакета?
@plural {n} linked file not found|{n} linked files not found не знайдено пов’язаних файлів: {n}|не знайдено пов’язаних файлів: {n}|не знайдено пов’язаних файлів: {n}
Can't render this file because it contains an unexpected character in line 182 and column 5.
+1
View File
@@ -4189,6 +4189,7 @@ mark-style Japanese Kiểu Nhật
Zoom to Selection Thu phóng đến vùng chọn
Zoom Tool Công cụ thu phóng
Zoom with Mouse Wheel Thu phóng bằng con lăn chuột
Scroll Sideways with Cmd/Ctrl + Wheel Cuộn ngang bằng Cmd/Ctrl + con lăn
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {n} tệp trong {folder} {note}. Hiện thư mục gói?
@plural {n} folder or file couldn't be read|{n} folders or files couldn't be read {n} thư mục hoặc tệp không thể đọc được
@plural {n} folder skipped, such as another app's or the system's folder or a hidden one|{n} folders skipped, such as other apps' and the system's folders and hidden ones Đã bỏ qua {n} thư mục, chẳng hạn thư mục của ứng dụng khác, thư mục hệ thống và thư mục ẩn
Can't render this file because it contains an unexpected character in line 204 and column 5.
+1
View File
@@ -3680,6 +3680,7 @@ digits Malayalam 马拉雅拉姆数字
Zoom to Selection 缩放到所选对象
Zoom Tool 缩放工具
Zoom with Mouse Wheel 使用鼠标滚轮缩放
Scroll Sideways with Cmd/Ctrl + Wheel 使用 Cmd/Ctrl + 滚轮水平滚动
Scrub Numeric Fields by Dragging 拖动以调整数值字段
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {folder} 中有 {n} 个文件{note}。要显示打包文件夹吗?
@plural {n} linked file not found|{n} linked files not found 找不到 {n} 个链接文件
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4716,6 +4716,7 @@ digits Malayalam 馬來亞拉姆數字
Zoom to Selection 縮放至選取範圍
Zoom Tool 縮放工具
Zoom with Mouse Wheel 使用滑鼠滾輪縮放
Scroll Sideways with Cmd/Ctrl + Wheel 使用 Cmd/Ctrl + 滾輪水平捲動
Scrub Numeric Fields by Dragging 拖曳以調整數值欄位
@plural {n} file in {folder} {note}. Show the package folder?|{n} files in {folder} {note}. Show the package folder? {folder} 中有 {n} 個檔案{note}。要顯示封裝資料夾嗎?
@plural {n} linked file not found|{n} linked files not found 找不到 {n} 個連結檔案
Can't render this file because it contains an unexpected character in line 6 and column 47.
+5
View File
@@ -456,6 +456,11 @@ fn category_fields(ui: &mut egui::Ui, app: &mut VectorcraftApp, d: &mut Dialog,
let v = d.fields.get(sp.key).cloned().unwrap_or(Value::Null);
let mark = found_mark(ui, d, sp.key);
match sp.kind {
// General › Scroll Sideways with Cmd/Ctrl + Wheel acts only while Zoom with Mouse Wheel
// is off: dimmed while it is on.
PrefKind::Bool if sp.key == "ctrlWheelScrollsSideways" => {
ui.add_enabled_ui(!d.bool("zoomWithMouseWheel"), |ui| bool_row(ui, d, sp.key, sp.label));
}
// Units › Numbers Without Units Are Points only tells points from picas: dimmed
// unless a unit is Picas.
PrefKind::Bool if sp.key == "numbersWithoutUnitsArePoints" => {
+35
View File
@@ -503,6 +503,41 @@ fn numbers_without_units_are_points_reaches_the_fields_and_dims_without_picas()
assert!(picas_in_use(d), "enabled with a unit in picas");
}
/// General › Scroll Sideways with Cmd/Ctrl + Wheel: its checkbox is dimmed while Zoom with
/// Mouse Wheel is checked in the dialog, and a click on it then leaves the setting as it was.
#[test]
fn scroll_sideways_with_cmd_wheel_dims_with_zoom_with_mouse_wheel() {
fn label(s: &egui::Shape, text: &str) -> Option<(egui::Color32, egui::Rect)> {
match s {
egui::Shape::Text(t) if t.galley.text() == text => t.galley.job.sections.first().map(|s| (s.format.color, t.visual_bounding_rect())),
egui::Shape::Vec(v) => v.iter().find_map(|s| label(s, text)),
_ => None,
}
}
let ctx = egui::Context::default();
crate::theme::install_fonts(&ctx);
let mut a = app();
let mut frame = |d: &mut Dialog, events: Vec<egui::Event>| {
let raw =
egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(600.0, 900.0))), events, ..Default::default() };
let mut out = ctx.run_ui(raw, |ui| category_fields(ui, &mut a, d, "General"));
out.textures_delta.clear();
out.shapes.iter().find_map(|c| label(&c.shape, "Scroll Sideways with Cmd/Ctrl + Wheel"))
};
let t = Tokens::get(&ctx);
for (zoom, color, what) in [(false, t.text, "enabled while Zoom with Mouse Wheel is off"), (true, t.text_disabled, "dimmed while it is on")] {
let mut d = Dialog::new("preferences", json!({"zoomWithMouseWheel": zoom, "ctrlWheelScrollsSideways": true}));
let (shown, at) = frame(&mut d, vec![]).unwrap_or_else(|| panic!("no label ({what})"));
assert_eq!(shown, color, "{what}");
let press =
|pressed| egui::Event::PointerButton { pos: at.center(), button: egui::PointerButton::Primary, pressed, modifiers: Default::default() };
frame(&mut d, vec![egui::Event::PointerMoved(at.center()), press(true)]);
frame(&mut d, vec![press(false)]);
// A click turns it off while it is enabled, and leaves it on while it is dimmed.
assert_eq!(d.fields["ctrlWheelScrollsSideways"], json!(zoom), "after a click, {what}");
}
}
/// 0.5.0 saved `powerSaving` for everyone (its default): it reads as Automatic, while the
/// choices this version offers are kept (#502).
#[test]
+1 -1
View File
@@ -100,7 +100,7 @@ the two can still win that race.
| `ui.key` / `ui.text` | `{key, shift?, alt?, cmd?}` / `{text}` | synthetic keyboard input |
| `ui.move` | `{x, y}` | screen-point pointer move |
| `ui.click` / `ui.drag` | `{x, y, button?, count?, shift?, alt?, ctrl?, cmd?}` / `{x, y, toX, toY, steps?, count?, button?, shift?, alt?, ctrl?, cmd?}` | egui pointer input; see synthetic input budgets above |
| `ui.wheel` | `{x, y, dy?, dx?, unit?: "line"\|"point", shift?, alt?, cmd?}` | a mouse wheel turn over screen point (x, y): `dy` notches up (+) or down, `dx` sideways. Over the canvas the wheel scrolls and Cmd- or Alt-wheel (Option on the Mac) zooms about the pointer; with the `zoomWithMouseWheel` preference the wheel and Alt-wheel zoom about the pointer, Shift-wheel scrolls up and down and Cmd-wheel (Ctrl on Windows and Linux) sideways. Over a focused numeric field (click it first) each notch steps its value as Up/Down do (Shift: ten, Cmd/Ctrl: a tenth) and the panel stays put; over anything else in a panel the wheel scrolls it |
| `ui.wheel` | `{x, y, dy?, dx?, unit?: "line"\|"point", shift?, alt?, cmd?}` | a mouse wheel turn over screen point (x, y): `dy` notches up (+) or down, `dx` sideways. Over the canvas the wheel scrolls, Cmd-wheel (Ctrl on Windows and Linux) scrolls sideways and Alt-wheel (Option on the Mac) zooms about the pointer (with the `ctrlWheelScrollsSideways` preference off, Cmd-wheel zooms too); with the `zoomWithMouseWheel` preference the wheel and Alt-wheel zoom about the pointer, Shift-wheel scrolls up and down and Cmd-wheel (Ctrl on Windows and Linux) sideways. Over a focused numeric field (click it first) each notch steps its value as Up/Down do (Shift: ten, Cmd/Ctrl: a tenth) and the panel stays put; over anything else in a panel the wheel scrolls it. Over the canvas, the wheel preferences in `docs/mcp.md` change what these keys do |
| `ui.set` | `{brightness?, panel?, rulers?, outline?, grid?, smartGuides?, boundingBox?, controlBar?, imageTracePreview?}` | `outline`: View › Outline for the active document only (each document has its own, a document opens in Preview, and `ui.inspect` shows it as `view.outline`; an error without a document). `imageTracePreview`: the Image Trace panel's Preview (`ui.inspect` shows it as `ui.image_trace_preview`) |
| `ui.dialog.set` / `.confirm` / `.cancel` | `{field, value}` or `{fields: [{field, value}…]}` | fill and submit the open dialog. `ui.dialog.set` takes the fields the dialog has (`ui.inspect`), `__` fields, `discard` on a dialog with a discard button, `preview` on one with a live preview, the fields that the dialog reads but adds only when a control changes (such as `searchFolder`, or `copy` in the Transform dialogs), and the fields it passes to the command it runs: every parameter of the `command` dialog's command (`ui.paramDialog`), and the `textureImage` that Load Texture… sets in the Glass and Texturizer effects; any other field is an error that lists the dialog's fields, and the dialog stays as it was `fields` sets the list (at most 256 items) in order (a missing `value` is `null`) and checks every item first: when one is refused, the call is an error and no field changes |
| `ui.screenshot` | `{path?, data?}` | capture the window (PNG), written to `path`; `data: true` sends it back as `pngBase64` too. The inline PNG is capped at 64 MiB: with a `path` the file is still written and `pngBase64` is omitted when the image is larger, while a path-less `data: true` request fails if either the raw RGBA image or the encoded PNG exceeds the cap. Needs a presented frame: with the screen locked or the window minimized/covered it fails after ~8 s with an explanatory error |
+6
View File
@@ -3693,6 +3693,12 @@ desktop app): in View › Pixel Preview, on softens placed and embedded bitmaps;
`disableAutoAddDelete` (off by default): on, the Pen no longer adds or deletes an anchor when a click lands on a
segment or an anchor of a selected path.
`ctrlWheelScrollsSideways` (on by default): on, Cmd/Ctrl-wheel scrolls the canvas sideways instead of zooming while
`zoomWithMouseWheel` is off; off, Cmd/Ctrl-wheel zooms about the pointer. Alt + Cmd/Ctrl-wheel and a pinch on a Mac
trackpad, on a touch screen or in the web build still zoom about the pointer. With `zoomWithMouseWheel` off, once a
trackpad gesture holds Alt, it zooms until it ends, also after Alt is let go. The control channel's
`ui.wheel` with `cmd: true` turns the wheel with Cmd/Ctrl held.
`gridlineEvery` (72 pt by default) and `gridSubdivisions` (8 by default) set the document grid that View › Show Grid
draws, and View › Snap to Grid snaps to its subdivisions. Changing either sets the grid of every open document.
`file.new` gives a new document that grid, and `document.open`, `file.newFromTemplate` and `file.revert` give it to
File diff suppressed because one or more lines are too long