WIP: save unverified diagram Delete candidate at user pause

This commit is contained in:
2026-09-12 04:58:44 -07:00
parent 0c38980c70
commit 60ea483430
14 changed files with 1308 additions and 36 deletions
+29 -6
View File
@@ -38,7 +38,6 @@ pub struct State {
context: Option<Context>,
tool: Option<Tool>,
pointer: Option<Point>,
focused: bool,
press: Option<Press>,
source: Option<Id>,
preview: Option<(Id, Position)>,
@@ -771,7 +770,6 @@ impl canvas::Program<Event> for StateCanvas<'_> {
}
canvas::Event::Window(iced::window::Event::Unfocused) => {
state.reset();
state.focused = false;
return None;
}
_ => cursor,
@@ -779,14 +777,40 @@ impl canvas::Program<Event> for StateCanvas<'_> {
let window = cursor.position();
let local = window.map(|p| Point::new(p.x - bounds.x, p.y - bounds.y));
let inside = local.is_some_and(|p| Self::content(bounds).contains(p));
if let canvas::Event::Keyboard(keyboard::Event::KeyPressed { key, modifiers, .. }) = event
&& state.focused
{
if let canvas::Event::Keyboard(keyboard::Event::KeyPressed { key, modifiers, .. }) = event {
use keyboard::{Key, key::Named};
if *key == Key::Named(Named::Escape) {
state.reset();
return Some(Action::publish(Event::Choose(Tool::Select)).and_capture());
}
if *key == Key::Named(Named::Delete)
&& self.editable
&& self.tool == Tool::Select
&& state.press.is_none()
&& state.pan_from.is_none()
&& state.source.is_none()
&& (modifiers.is_empty() || *modifiers == keyboard::Modifiers::SHIFT)
{
let scene = self.scene(state)?;
let placement = scene
.view
.nodes
.iter()
.find(|node| node.element == self.selected || node.id == self.selected);
let object = placement.map_or(self.selected, |node| node.element);
if placement.is_none() && !scene.view.edges.iter().any(|edge| edge.id == object) {
return None;
}
return Some(
Action::publish(Event::Remove(crate::app::diagram_removal::Intent {
context: self.context,
object,
placement: placement.map(|node| node.id),
model: modifiers.shift(),
}))
.and_capture(),
);
}
if modifiers.is_empty() {
let pan = match key.as_ref() {
Key::Named(Named::ArrowLeft) => Some(Vector::new(60., 0.)),
@@ -804,7 +828,6 @@ impl canvas::Program<Event> for StateCanvas<'_> {
let scene = self.scene(state)?;
match event {
canvas::Event::Mouse(mouse::Event::ButtonPressed(button)) => {
state.focused = inside;
if !inside {
return None;
}
@@ -24,6 +24,7 @@ pub enum Tool {
#[derive(Debug, Clone)]
pub enum Event {
Remove(crate::app::diagram_removal::Intent),
Choose(Tool),
CreateView(Id),
Select(Context, Id),
@@ -70,6 +71,7 @@ pub enum Event {
impl Event {
pub fn context(&self) -> Option<Context> {
match self {
Self::Remove(intent) => Some(intent.context),
Self::Choose(_) | Self::CreateView(_) => None,
Self::Select(c, _)
| Self::Pan(c, _)
+26 -6
View File
@@ -139,11 +139,14 @@ pub fn popup(app: &App, opened: &Opened, clean: bool) -> Option<Menu<Message>> {
true,
));
}
entries.push(item(
"Hide from this diagram",
Message::Command(Command::Delete(node.id)),
true,
));
entries.push(
item(
"Hide from this diagram",
Message::Command(Command::Delete(node.id)),
true,
)
.shortcut("Delete"),
);
}
}
if let Some(relation) = project.relations.get(&id)
@@ -184,7 +187,24 @@ pub fn popup(app: &App, opened: &Opened, clean: bool) -> Option<Menu<Message>> {
}
if id != project.id {
entries.push(Entry::separator());
entries.push(item("Delete from model…", Message::Delete, true));
entries.push(item("Delete from model…", Message::Delete, true).shortcut(
if context.is_some_and(|context| {
context.diagram != id
&& (request.placement.is_some()
|| projection::project_view(project, context.diagram)
.edges
.iter()
.any(|edge| edge.id == id))
}) {
if request.placement.is_some() {
"Shift+Delete"
} else {
"Delete / Shift+Delete"
}
} else {
""
},
));
}
}
Some(Menu {
+6 -1
View File
@@ -173,7 +173,12 @@ pub fn view<'a>(app: &'a App, machine: Id, mut out: Column<'a, Message>) -> Elem
.width(Fill)
.height(Fill)
.into();
out = out.push(canvas.map(event));
out = out.push(crate::diagram::focus::wrap(
canvas.map(event),
context,
crate::app::diagram_removal::enabled(app),
Message::DiagramTraverse,
));
let base: Element<'_, Message> = container(out.spacing(8))
.padding(14)
.width(Fill)