Files
Ely-GPUI-Components/src/canvas/writing.rs
T
ZacharyZhang-NY 4498ff09dc Canvas · Graphs and boards: node graph, flow chart, mind map, whiteboard
NodeGraph joins Nodes by wires between typed Ports: a title drags a
node, a drag out of an output lands on an input of the same kind, an
input takes one wire, and a press on a wired input lifts its wire.
Links join shapes on the plane and follow them, straight or at right
angles, with an arrow and words; the Connector tool draws them and the
Note tool drops a sticky note. A double press with Select writes on a
shape. FlowChart draws Steps as ellipses, boxes and diamonds with their
words. MindMap lays topics out from a root, half to each side, and asks
the owner to add, remove and rename by key. Whiteboard keeps its own
tool, view and selection over a board it hands back after each change.
Painting moves to canvas::paint; a press on the tool layer goes through
canvas::press, and the layer focuses itself and asks to delete.
2026-09-27 08:22:54 -04:00

55 lines
1.8 KiB
Rust

use std::rc::Rc;
use gpui::{
AnyElement, App, Entity, 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.
pub(super) fn begin(
editing: &Entity<Editing>,
key: SharedString,
words: String,
on_text: Option<OnPair>,
window: &mut Window,
cx: &mut App,
) {
log::info!("canvas: writing on {key}");
editing.update(cx, |editing, _| {
editing.on_commit = Some(Rc::new(
move |text: &SharedString, window: &mut Window, cx: &mut App| {
log::info!("canvas: {key} reads {text:?}");
if let Some(on_text) = &on_text {
on_text(&key, text, window, cx);
}
},
));
});
Editing::begin(editing, words, window, cx);
}
/// 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();
Some(
div()
.absolute()
.left(Pixels::from(frame.x))
.top(Pixels::from(frame.y))
.w(Pixels::from(frame.w))
.on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
.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));
}
})
.child(Input::new(&field))
.into_any_element(),
)
}