1 parent
ff7f3204d5
commit
a5003da9d7
3 files changed
+48
-3
No files matched your search
@@ -387,8 +387,19 @@ pub(crate) fn handle(app: &mut SolveApp, ui: &mut egui::Ui, rect: Rect, resp: &e
|
|||||||
} else if !primary_down && !primary_released {
|
} else if !primary_down && !primary_released {
|
||||||
app.viewport.primary_nav = None;
|
app.viewport.primary_nav = None;
|
||||||
}
|
}
|
||||||
// The fixed navigation mode (navigation bar) or the preset's left-button binding.
|
// Hold Space for a momentary pan: the hand tool of design apps. It overrides whatever the
|
||||||
let primary_nav = app.viewport.nav.or(app.viewport.primary_nav);
|
// left button would otherwise do - selecting, dragging geometry, the preset's binding or the
|
||||||
|
// navigation bar's fixed mode - and lasts only while the key is held. Space still types in a
|
||||||
|
// text field, and while a dimension's text is being edited, so those keep the keyboard.
|
||||||
|
let space_pan = (inside || primary_down)
|
||||||
|
&& !ui.ctx().egui_wants_keyboard_input()
|
||||||
|
&& !crate::dim_view::editing()
|
||||||
|
&& ui.input(|i| i.key_down(egui::Key::Space));
|
||||||
|
if space_pan {
|
||||||
|
ui.ctx().set_cursor_icon(if primary_down { egui::CursorIcon::Grabbing } else { egui::CursorIcon::Grab });
|
||||||
|
}
|
||||||
|
// The fixed navigation mode (navigation bar), a held Space, or the preset's left-button binding.
|
||||||
|
let primary_nav = if space_pan { Some(NavMode::Pan) } else { app.viewport.nav.or(app.viewport.primary_nav) };
|
||||||
let button = if middle {
|
let button = if middle {
|
||||||
Some(crate::prefs::NavButton::Middle)
|
Some(crate::prefs::NavButton::Middle)
|
||||||
} else if secondary_down {
|
} else if secondary_down {
|
||||||
|
|||||||
@@ -1139,7 +1139,7 @@ fn page(app: &mut SolveApp, ui: &mut egui::Ui, t: &Tokens) {
|
|||||||
note(ui, crate::i18n::tr("nav.touchpad.help"));
|
note(ui, crate::i18n::tr("nav.touchpad.help"));
|
||||||
} else {
|
} else {
|
||||||
let snap_help = if app.preferences.nav == OPENSCAD_NAV { "" } else { "; hold Shift during orbit to snap" };
|
let snap_help = if app.preferences.nav == OPENSCAD_NAV { "" } else { "; hold Shift during orbit to snap" };
|
||||||
let raw_help = format!("{}; Ctrl+left drag on empty space orbits{snap_help}; the wheel zooms", nav_preset(&app.preferences.nav).help);
|
let raw_help = format!("{}; Ctrl+left drag on empty space orbits{snap_help}; hold Space to pan; the wheel zooms", nav_preset(&app.preferences.nav).help);
|
||||||
note(ui, crate::i18n::tr_label(&raw_help));
|
note(ui, crate::i18n::tr_label(&raw_help));
|
||||||
}
|
}
|
||||||
ui.label(crate::i18n::tr_label("Context menu"));
|
ui.label(crate::i18n::tr_label("Context menu"));
|
||||||
|
|||||||
@@ -4111,6 +4111,40 @@ mod tests {
|
|||||||
app
|
app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn space(pressed: bool) -> egui::Event {
|
||||||
|
egui::Event::Key { key: egui::Key::Space, physical_key: None, pressed, repeat: false, modifiers: egui::Modifiers::default() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Holding Space is a momentary pan: the drag moves the view rather than the geometry under the
|
||||||
|
/// pointer, in every preset. The point is over the sketch's own point, so without Space this
|
||||||
|
/// drag would drag it (and the undo stack would grow).
|
||||||
|
#[test]
|
||||||
|
fn holding_space_pans_instead_of_dragging_geometry() {
|
||||||
|
for preset in crate::prefs::NAV_PRESETS.iter().map(|p| p.id) {
|
||||||
|
let ctx = egui::Context::default();
|
||||||
|
let mut app = hover_app(false);
|
||||||
|
app.preferences.nav = preset.into();
|
||||||
|
app.ui.show_origin = false;
|
||||||
|
hover_frame(&mut app, &ctx, vec![]);
|
||||||
|
let point = projection(&app, app.viewport.rect.unwrap()).to_screen(Vec3::ZERO).unwrap();
|
||||||
|
let before = app.cam;
|
||||||
|
let undo = app.session.undo.len();
|
||||||
|
let press = |pressed: bool, at: Pos2| egui::Event::PointerButton {
|
||||||
|
pos: at,
|
||||||
|
button: egui::PointerButton::Primary,
|
||||||
|
pressed,
|
||||||
|
modifiers: egui::Modifiers::default(),
|
||||||
|
};
|
||||||
|
hover_frame(&mut app, &ctx, vec![space(true)]);
|
||||||
|
hover_frame(&mut app, &ctx, vec![space(true), egui::Event::PointerMoved(point), press(true, point)]);
|
||||||
|
hover_frame(&mut app, &ctx, vec![space(true), egui::Event::PointerMoved(point + vec2(40.0, 25.0))]);
|
||||||
|
assert_ne!(app.cam, before, "{preset}: holding Space must pan the view");
|
||||||
|
assert_eq!(app.session.undo.len(), undo, "{preset}: holding Space must not edit the design");
|
||||||
|
assert!(app.viewport.point_drag.is_none(), "{preset}: holding Space must not drag geometry");
|
||||||
|
hover_frame(&mut app, &ctx, vec![press(false, point + vec2(40.0, 25.0)), space(false)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ctrl_left_drag_from_empty_space_orbits_in_every_preset() {
|
fn ctrl_left_drag_from_empty_space_orbits_in_every_preset() {
|
||||||
for preset in crate::prefs::NAV_PRESETS.iter().map(|p| p.id) {
|
for preset in crate::prefs::NAV_PRESETS.iter().map(|p| p.id) {
|
||||||
|
|||||||
Reference in new issue
Block a user