Compact diagram instructions and add contextual help overlay

This commit is contained in:
2026-09-24 23:06:53 -07:00
parent 715036e132
commit e0812b3932
12 changed files with 566 additions and 114 deletions
+73 -1
View File
@@ -6,6 +6,8 @@ mod architecture_authoring_tests;
mod behavior_removal_tests;
mod checkpoints;
#[cfg(test)]
mod context_help_tests;
#[cfg(test)]
mod diagram_focus_tests;
pub(crate) mod diagram_removal;
#[cfg(test)]
@@ -376,6 +378,9 @@ pub enum Message {
ExactStrings(bool),
Page(Page),
Guide(crate::guide::Event),
ContextHelp(crate::guide::Topic),
CloseContextHelp,
Help,
Traceability(crate::views::traceability::Event),
ReviewLayerTraces,
Behavior(crate::behavior::Event),
@@ -521,6 +526,7 @@ pub struct App {
/// Home resumes this page; explicit Architecture navigation remains separate.
last_workspace_page: Page,
pub guide: crate::guide::State,
pub context_help: bool,
pub traceability: crate::views::traceability::State,
pub behavior: crate::behavior::State,
pub data_state: crate::data_view::State,
@@ -643,6 +649,7 @@ impl App {
page: Page::Diagram,
last_workspace_page: Page::Diagram,
guide: crate::guide::State::default(),
context_help: false,
traceability: Default::default(),
behavior: Default::default(),
data_state: Default::default(),
@@ -1320,7 +1327,7 @@ impl App {
return Some(Message::Escape);
}
if key == keyboard::Key::Named(keyboard::key::Named::F1) {
return Some(Message::Page(Page::Guide));
return Some(Message::Help);
}
if key == keyboard::Key::Named(keyboard::key::Named::F3) {
return Some(Message::SourceNavigation(
@@ -1348,6 +1355,38 @@ impl App {
])
}
pub fn update(&mut self, message: Message) -> Task<Message> {
// Help owns user input before any canvas/reference fast path can act.
// Passive results may finish; they retain their normal lifetime checks.
if self.context_help
&& !matches!(
message,
Message::Guide(_)
| Message::CloseContextHelp
| Message::Escape
| Message::Request(Pending::Close(_))
| Message::CheckpointWritten(..)
| Message::CheckpointTick
| Message::CheckpointLoaded(..)
| Message::WindowResized(_)
| Message::CanvasResized(_)
| Message::DiagramRevealViewport(..)
| Message::SourceViewport(_)
| Message::Lint(_)
| Message::Linted(..)
| Message::Saved(_)
| Message::Hosted(crate::hosted::Event::Completed(..))
| Message::Loaded(_)
| Message::IncludesLoaded(..)
| Message::SavePath(_)
| Message::SourceRecovered(_)
| Message::Exported(_)
| Message::SourceSymbolsReady(_)
| Message::SourceRenameReady(_)
| Message::DiagramUsagesReady(_)
)
{
return Task::none();
}
let preview_read_only = self.process_preview_primary().is_some();
let selection_boundary = self.multiselect_boundary();
// Reject delayed gestures before they can retire newer input ownership.
@@ -1900,6 +1939,10 @@ impl App {
message,
Message::Escape | Message::Request(Pending::Close(_))
) {
if self.context_help {
self.context_help = false;
return Task::none();
}
if self.hosted.visible {
self.hosted.visible = false;
return Task::none();
@@ -2091,6 +2134,7 @@ impl App {
}
pub(crate) fn scenario_focus_owner(&self) -> Option<crate::behavior::scenario::focus::Stamp> {
if self.busy
|| self.context_help
|| self.hosted.visible
|| self.workflow.is_some()
|| self.architecture.is_some()
@@ -2787,6 +2831,34 @@ impl App {
);
}
}
Message::ContextHelp(topic) => {
self.guide.update(crate::guide::Event::Topic(topic));
self.context_help = true;
return iced::widget::operation::snap_to(
crate::guide::ARTICLE_SCROLL_ID,
iced::widget::scrollable::RelativeOffset::START,
);
}
Message::CloseContextHelp => {
self.context_help = false;
}
Message::Help => {
let topic = match self.page {
Page::Diagram => Some(crate::guide::Topic::Nesting),
Page::Behavior => self.behavior.active_owner.and_then(|id| {
self.project()
.elements
.get(&id)
.map(|element| match element.kind() {
Kind::StateMachine => crate::guide::Topic::States,
Kind::Scenario => crate::guide::Topic::Scenarios,
_ => crate::guide::Topic::Chains,
})
}),
_ => None,
};
return self.update(topic.map_or(Message::Page(Page::Guide), Message::ContextHelp));
}
Message::ExactStrings(enabled) => {
if let Some(d) = &mut self.draft {
match d.set_exact(enabled) {