mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 13:17:19 -06:00
View: Escape that cancels a ruler or Tools move does not reach the tool
An Escape that cancels a ruler-origin drag or a floating Tools panel move now stops there: the active tool does not receive it, so a tool's own Escape action (for example Intertwine returning to the Selection tool) waits for the next press. The ruler-origin test also covers the drawer and Global Edit.
This commit is contained in:
@@ -205,8 +205,9 @@ pub fn handle(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
presentation_keys(app, ctx, escape_pair);
|
||||
return;
|
||||
}
|
||||
let escape_held_by_drag =
|
||||
crate::canvas::dragging(ctx) || crate::canvas::ruler_origin_dragging(ctx) || crate::tools_float::escape_cancelled_move(ctx);
|
||||
// Escape that cancels a ruler-origin drag or floating Tools move skips the tool and later Escape actions.
|
||||
let escape_ended_gesture = crate::canvas::ruler_origin_dragging(ctx) || crate::tools_float::escape_cancelled_move(ctx);
|
||||
let escape_held_by_drag = crate::canvas::dragging(ctx) || escape_ended_gesture;
|
||||
let typing = ctx.egui_wants_keyboard_input();
|
||||
// Escape closes Edit Toolbar's drawer first (egui drops a drag from it on Escape already).
|
||||
if app.ui.tools_drawer && !typing && !escape_held_by_drag && ctx.input_mut(|i| i.consume_key(Modifiers::NONE, Key::Escape)) {
|
||||
@@ -226,6 +227,10 @@ pub fn handle(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
if (text || !busy) && ctx.input(|i| runs_a_command(i, k, text)) {
|
||||
continue;
|
||||
}
|
||||
if k == Key::Escape && escape_ended_gesture {
|
||||
remember_escape_pair(ctx, k, escape_pair);
|
||||
continue;
|
||||
}
|
||||
// A key the tool claims (Esc with a loaded place cursor) is only the tool's.
|
||||
let claimed = app.session.tool_claims_key(tk, view);
|
||||
let mods = ctx.input(|i| {
|
||||
@@ -276,10 +281,7 @@ pub fn handle(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
}
|
||||
}
|
||||
// An Escape that ended something can start a pair too. One that closed a popup cannot.
|
||||
if k == Key::Escape && escape_pair.is_some() && !egui::Popup::is_any_open(ctx) {
|
||||
let now = ctx.input(|i| i.time);
|
||||
ctx.data_mut(|d| d.insert_temp(escape_pair_id(), now));
|
||||
}
|
||||
remember_escape_pair(ctx, k, escape_pair);
|
||||
if k == Key::Enter && !busy && !claimed {
|
||||
// Enter with a selection tool opens the Move dialog, as a double-click on its button
|
||||
// does.
|
||||
@@ -344,6 +346,13 @@ pub fn handle(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
single_key_shortcuts(app, ctx);
|
||||
}
|
||||
|
||||
fn remember_escape_pair(ctx: &egui::Context, key: Key, escape_pair: Option<bool>) {
|
||||
if key == Key::Escape && escape_pair.is_some() && !egui::Popup::is_any_open(ctx) {
|
||||
let now = ctx.input(|i| i.time);
|
||||
ctx.data_mut(|d| d.insert_temp(escape_pair_id(), now));
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch unmodified text keys to command bindings or tools.
|
||||
fn single_key_shortcuts(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
// Single-key tool shortcuts (no Cmd/Ctrl/Alt). With a layout without Latin letters (Persian,
|
||||
|
||||
@@ -365,10 +365,26 @@ fn cancelling_tools_move_keeps_the_next_escape_action() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancelling_tools_move_keeps_the_tools_escape() {
|
||||
for mode in [0, 1, 2] {
|
||||
let ctx = egui::Context::default();
|
||||
let mut app = in_screen_mode(&ctx, mode);
|
||||
app.select_tool("intertwine");
|
||||
let (original, to) = begin_tools_move(&mut app, &ctx);
|
||||
frame(&mut app, &ctx, escape());
|
||||
assert_eq!(app.ui.toolbar_pos, original, "move canceled in mode {mode}");
|
||||
assert_eq!(app.session.tool_id(), "intertwine", "move Escape keeps the tool in mode {mode}");
|
||||
release_drag(&mut app, &ctx, to);
|
||||
frame(&mut app, &ctx, escape());
|
||||
assert_eq!(app.session.tool_id(), "selection", "later Escape reaches the tool in mode {mode}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancelling_ruler_origin_drag_keeps_the_next_escape_action() {
|
||||
for mode in [0, 1, 2] {
|
||||
for action in ["pattern", "isolation", "flyout"] {
|
||||
for action in ["drawer", "pattern", "isolation", "global", "flyout"] {
|
||||
let ctx = egui::Context::default();
|
||||
let mut app = in_screen_mode(&ctx, mode);
|
||||
let to = begin_ruler_origin_drag(&mut app, &ctx);
|
||||
@@ -384,6 +400,22 @@ fn cancelling_ruler_origin_drag_keeps_the_next_escape_action() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancelling_ruler_origin_drag_keeps_the_tools_escape() {
|
||||
for mode in [0, 1, 2] {
|
||||
let ctx = egui::Context::default();
|
||||
let mut app = in_screen_mode(&ctx, mode);
|
||||
app.select_tool("intertwine");
|
||||
let to = begin_ruler_origin_drag(&mut app, &ctx);
|
||||
frame(&mut app, &ctx, escape());
|
||||
assert_eq!(app.session.tool_id(), "intertwine", "drag Escape keeps the tool in mode {mode}");
|
||||
release_drag(&mut app, &ctx, to);
|
||||
assert!(!crate::canvas::ruler_origin_dragging(&ctx));
|
||||
frame(&mut app, &ctx, escape());
|
||||
assert_eq!(app.session.tool_id(), "selection", "later Escape reaches the tool in mode {mode}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_popup_takes_escape_before_full_screen_exits() {
|
||||
let ctx = egui::Context::default();
|
||||
|
||||
Reference in New Issue
Block a user