Fix inline architecture naming and captured Escape cancellation
Rust checks / check (ubuntu-latest) (push) Canceled after 0s
Rust checks / check (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-09-10 11:10:24 -07:00
parent 1797516f46
commit 7d1df4f369
9 changed files with 722 additions and 21 deletions
@@ -3,6 +3,8 @@ use super::*;
use iced::widget::{button, column, pick_list, row, scrollable, text, text_input};
use serde::{Deserialize, Serialize};
mod palette;
#[cfg(test)]
mod tests;
pub use palette::view as palette;
#[derive(Debug, Clone)]
@@ -21,9 +23,35 @@ pub enum Event {
Filter(Filter),
ShowPlaced(bool),
Page(usize),
Edit,
CapturedEscape,
Cancel,
}
pub fn subscription(app: &App) -> Subscription<Message> {
if app.architecture.as_ref().is_some_and(State::inline) {
iced::event::listen_with(captured_escape)
} else {
Subscription::none()
}
}
fn captured_escape(
event: iced::Event,
status: iced::event::Status,
_: iced::window::Id,
) -> Option<Message> {
// A focused Iced text input captures Escape while dropping its focus. Only
// inline architecture naming opts into also cancelling that same keypress.
(status == iced::event::Status::Captured
&& matches!(
event,
iced::Event::Keyboard(iced::keyboard::Event::KeyPressed {
key: iced::keyboard::Key::Named(iced::keyboard::key::Named::Escape),
..
})
))
.then_some(Message::Architecture(Event::CapturedEscape))
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub enum Filter {
@@ -336,14 +364,20 @@ impl App {
}
return iced::widget::operation::focus("architecture-name");
}
Event::CapturedEscape => {
if self.architecture.as_ref().is_some_and(State::inline) {
return self.architecture_event(Event::Cancel);
}
}
Event::Cancel => {
self.architecture = None;
self.canvas_epoch = self.canvas_epoch.wrapping_add(1);
self.status = "Cancelled · Select / move".into();
}
Event::Name(value) => {
if value.len() <= 16384
&& let Some(s) = &mut self.architecture
&& let (Intent::Create { name, .. } | Intent::Rename { name, .. }) =
&& let Intent::Create { name, .. } | Intent::Rename { name, .. } =
&mut s.saved.intent
{
*name = value;
@@ -375,13 +409,6 @@ impl App {
s.saved.page = page.min(1_000_000);
}
}
Event::Edit => {
self.canvas_epoch = self.canvas_epoch.wrapping_add(1);
if let Some(s) = &mut self.architecture {
s.saved.placing = false;
}
return iced::widget::operation::focus("architecture-name");
}
Event::Pick(id) => {
if !candidates(self)
.iter()
@@ -422,7 +449,10 @@ impl App {
}
}
Event::Click(context, point) => {
if self.route_context() != Some(context) {
if self.route_context() != Some(context)
|| !point.x.is_finite()
|| !point.y.is_finite()
{
return Task::none();
}
if self.architecture.as_ref().is_some_and(|s| s.saved.placing) {
@@ -460,6 +490,10 @@ impl App {
self.status =
"The diagram changed. The name is retained; cancel and restart this placement."
.into();
if let Some(s) = &mut self.architecture {
s.saved.placing = false;
s.error = Some(self.status.clone());
}
return;
}
let diagram = s.saved.diagram;
@@ -553,9 +587,10 @@ pub fn inline_editor(app: &App) -> Option<Element<'_, Message>> {
row![
iced::widget::Space::new().width(x),
iced::widget::opaque(
iced::widget::container(name_editor(app))
iced::widget::container(scrollable(name_editor(app)))
.padding(10)
.width(width)
.max_height((size.height - y - 8.).max(0.))
.style(crate::style::card)
)
]