Add named behavior creation and verified textual authoring examples
This commit is contained in:
@@ -14,6 +14,7 @@ use iced::{
|
||||
};
|
||||
use oa_core::*;
|
||||
use std::collections::BTreeMap;
|
||||
pub(crate) mod creation;
|
||||
pub(crate) mod scenario;
|
||||
pub(crate) mod state_canvas;
|
||||
pub(crate) mod state_edit;
|
||||
@@ -731,6 +732,7 @@ mod scenario_scroll {
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
Creation(creation::Event),
|
||||
Topology(topology::Event),
|
||||
Scenario(scenario::Event),
|
||||
States(states::Event),
|
||||
@@ -740,7 +742,8 @@ impl Event {
|
||||
pub fn starts_form(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Topology(topology::Event::Start(..))
|
||||
Self::Creation(creation::Event::Open(..))
|
||||
| Self::Topology(topology::Event::Start(..))
|
||||
| Self::Scenario(scenario::Event::Start(..))
|
||||
| Self::States(states::Event::Start(..) | states::Event::Edit(..))
|
||||
)
|
||||
@@ -749,6 +752,7 @@ impl Event {
|
||||
matches!(
|
||||
self,
|
||||
Self::Submit
|
||||
| Self::Creation(creation::Event::Submit)
|
||||
| Self::Topology(topology::Event::Submit)
|
||||
| Self::Scenario(scenario::Event::Submit)
|
||||
| Self::States(states::Event::Submit)
|
||||
@@ -757,6 +761,7 @@ impl Event {
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct State {
|
||||
pub(crate) creation: creation::State,
|
||||
pub active_owner: Option<Id>,
|
||||
pub diagram: state_view::State,
|
||||
pub(crate) topology: topology::State,
|
||||
@@ -773,6 +778,7 @@ struct RecoveryDraft {
|
||||
}
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
enum RecoveryKind {
|
||||
Creation,
|
||||
State,
|
||||
Scenario,
|
||||
Process,
|
||||
@@ -782,6 +788,7 @@ impl State {
|
||||
/// viewport geometry and document/revision tokens never cross a restart.
|
||||
pub fn recovery_snapshot(&self) -> Result<Option<serde_json::Value>, String> {
|
||||
let drafts = [
|
||||
(RecoveryKind::Creation, self.creation.recovery_snapshot()?),
|
||||
(RecoveryKind::State, self.states.recovery_snapshot()?),
|
||||
(RecoveryKind::Scenario, self.scenario.recovery_snapshot()?),
|
||||
(RecoveryKind::Process, self.topology.recovery_snapshot()?),
|
||||
@@ -817,6 +824,9 @@ impl State {
|
||||
}
|
||||
let mut restored = Self::default();
|
||||
match saved.kind {
|
||||
RecoveryKind::Creation => {
|
||||
restored.creation = creation::State::from_recovery(saved.draft)?
|
||||
}
|
||||
RecoveryKind::State => restored.states = states::State::from_recovery(saved.draft)?,
|
||||
RecoveryKind::Scenario => {
|
||||
restored.scenario = scenario::State::from_recovery(saved.draft)?
|
||||
@@ -831,7 +841,7 @@ impl State {
|
||||
}
|
||||
|
||||
pub fn has_pending(&self) -> bool {
|
||||
self.pending_owner().is_some()
|
||||
self.creation.has_pending() || self.pending_owner().is_some()
|
||||
}
|
||||
|
||||
pub fn pending_owner(&self) -> Option<Id> {
|
||||
@@ -844,7 +854,9 @@ impl State {
|
||||
/// Prepare the active form without discarding inputs. The caller must execute
|
||||
/// this exact command and acknowledge only a successful document transaction.
|
||||
pub fn prepare_pending(&self, p: &Project) -> Result<Option<Command>, String> {
|
||||
if self.topology.pending_owner().is_some() {
|
||||
if self.creation.has_pending() {
|
||||
self.creation.prepare_pending(p).map(Some)
|
||||
} else if self.topology.pending_owner().is_some() {
|
||||
self.topology.prepare_pending(p).map(Some)
|
||||
} else if self.scenario.pending_owner().is_some() {
|
||||
self.scenario.prepare_pending(p).map(Some)
|
||||
@@ -858,6 +870,7 @@ impl State {
|
||||
/// Clear the active form after its prepared command commits successfully.
|
||||
/// Rejected commands must leave the form available for repair and retry.
|
||||
pub fn acknowledge_commit(&mut self) {
|
||||
self.creation.acknowledge_commit();
|
||||
self.topology.acknowledge_commit();
|
||||
self.scenario.acknowledge_commit();
|
||||
self.states.acknowledge_commit();
|
||||
@@ -867,7 +880,8 @@ impl State {
|
||||
if self.has_pending()
|
||||
&& matches!(
|
||||
&event,
|
||||
Event::Topology(topology::Event::Start(..))
|
||||
Event::Creation(creation::Event::Open(..))
|
||||
| Event::Topology(topology::Event::Start(..))
|
||||
| Event::Scenario(scenario::Event::Start(..))
|
||||
| Event::States(states::Event::Start(..) | states::Event::Edit(..))
|
||||
)
|
||||
@@ -885,6 +899,7 @@ impl State {
|
||||
return Ok(None);
|
||||
}
|
||||
match event {
|
||||
Event::Creation(event) => self.creation.update(p, event),
|
||||
Event::Topology(event) => self.topology.update(p, event),
|
||||
Event::Scenario(event) => self.scenario.update(p, event),
|
||||
Event::States(event) => self.states.update(p, event),
|
||||
@@ -898,6 +913,9 @@ impl State {
|
||||
|
||||
pub fn view(app: &App) -> Element<'_, Message> {
|
||||
let p = app.project();
|
||||
if let Some(card) = app.behavior.creation.view(p) {
|
||||
return card.map(|event| Message::Behavior(Event::Creation(event)));
|
||||
}
|
||||
let choices = p
|
||||
.elements
|
||||
.values()
|
||||
@@ -916,7 +934,16 @@ pub fn view(app: &App) -> Element<'_, Message> {
|
||||
.cloned();
|
||||
let mut out = column![heading("Behavior & scenarios", "Follow exchanges and operating conditions. Select a message, state or transition to edit it.")].spacing(14);
|
||||
let Some(selected) = selected else {
|
||||
return out.push(label("Start with a Process, Scenario or State machine using Create element. Add occurrences or regions inside it to describe behavior.")).padding(24).into();
|
||||
return out
|
||||
.push(label(
|
||||
"Start a named process, scenario or state machine, then model its behavior here.",
|
||||
))
|
||||
.push(action(
|
||||
"New",
|
||||
Message::Behavior(Event::Creation(creation::Event::Open(app.layer))),
|
||||
))
|
||||
.padding(24)
|
||||
.into();
|
||||
};
|
||||
let e = &p.elements[&selected.id];
|
||||
let compact_canvas = matches!(
|
||||
@@ -930,10 +957,17 @@ pub fn view(app: &App) -> Element<'_, Message> {
|
||||
out = column![].spacing(6);
|
||||
}
|
||||
out = out.push(
|
||||
pick_list(choices, Some(selected), Message::BehaviorOwner)
|
||||
.width(Fill)
|
||||
.text_size(13)
|
||||
.padding(if compact_canvas { 6 } else { 10 }),
|
||||
row![
|
||||
pick_list(choices, Some(selected), Message::BehaviorOwner)
|
||||
.width(Fill)
|
||||
.text_size(13)
|
||||
.padding(if compact_canvas { 6 } else { 10 }),
|
||||
action(
|
||||
"New",
|
||||
Message::Behavior(Event::Creation(creation::Event::Open(app.layer)))
|
||||
)
|
||||
]
|
||||
.spacing(8),
|
||||
);
|
||||
if matches!(e.kind(), Kind::Process | Kind::FunctionalChain) {
|
||||
return topology::view(app, e.id, out);
|
||||
|
||||
Reference in New Issue
Block a user