mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-11 02:19:56 -06:00
Canvas: a General option makes Cmd/Ctrl-wheel scroll the canvas sideways
Squashed from #5023 onto main.
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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.
|
@@ -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" => {
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user