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.
This commit is contained in:
1 parent
ec1988cd6f
commit
4498ff09dc
28 files changed
+3068
-240
No files matched your search
@@ -0,0 +1,54 @@
|
||||
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(),
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user