Canvas · Graphs and boards: a field hands focus back on Enter and Escape

writing::begin records the owner's focus, the mind map's or the tool
layer's, through forms::Editing::returning. The field keeps its words on
Enter's release and drops them on Escape, and both hand focus back, so
the map's arrows and the board's Backspace work at once after a write.
This commit is contained in:
ZacharyZhang-NY committed 2026-09-27 08:41:05 -04:00
1 parent 538c3ed93f
commit 31bd483dc5
8 files changed
+81 -12

No files matched your search

+19 -5
View File
@@ -1,19 +1,20 @@
use std::rc::Rc;
use gpui::{
AnyElement, App, Entity, InteractiveElement, IntoElement, MouseButton, ParentElement, Pixels,
SharedString, Styled, Window, div,
AnyElement, App, Entity, FocusHandle, InteractiveElement, IntoElement, MouseButton,
ParentElement, Pixels, SharedString, Styled, Window, div,
};
use super::{gesture::OnPair, view::Frame};
use crate::forms::{Editing, Input};
/// Opens a field on the words of what `key` names. Enter or leaving hands them to the owner; Escape drops them.
/// Opens a field on the words of what `key` names. Enter or leaving hands them to the owner; Escape drops them. Enter and Escape hand focus back to `back`.
pub(super) fn begin(
editing: &Entity<Editing>,
key: SharedString,
words: String,
on_text: Option<OnPair>,
back: FocusHandle,
window: &mut Window,
cx: &mut App,
) {
@@ -29,12 +30,13 @@ pub(super) fn begin(
));
});
Editing::begin(editing, words, window, cx);
editing.update(cx, |editing, _| editing.returning(back));
}
/// The open field over `frame`, in view pixels.
pub(super) fn field(editing: &Entity<Editing>, frame: Frame, cx: &App) -> Option<AnyElement> {
let field = editing.read(cx).field()?;
let closing = editing.clone();
let (closing, keeping) = (editing.clone(), editing.clone());
Some(
div()
.absolute()
@@ -45,7 +47,19 @@ pub(super) fn field(editing: &Entity<Editing>, frame: Frame, cx: &App) -> Option
.on_key_down(move |event, window, cx| {
if event.keystroke.key == "escape" {
cx.stop_propagation();
closing.update(cx, |editing, cx| editing.finish(true, window, cx));
closing.update(cx, |editing, cx| {
editing.finish(true, window, cx);
editing.give_back(window);
});
}
})
.on_key_up(move |event, window, cx| {
if event.keystroke.key == "enter" {
cx.stop_propagation();
keeping.update(cx, |editing, cx| {
editing.finish(false, window, cx);
editing.give_back(window);
});
}
})
.child(Input::new(&field))