Complete source 6 engineering workflows and preserve release validation evidence
This commit is contained in:
@@ -12,6 +12,7 @@ use iced::{
|
||||
};
|
||||
use oa_core::{transitions::*, *};
|
||||
use std::collections::BTreeSet;
|
||||
mod communication;
|
||||
pub(crate) mod recovery;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -31,6 +32,7 @@ pub enum Event {
|
||||
Scope(String),
|
||||
MappingTarget(Id, Choice),
|
||||
MappingKind(Id, Kind),
|
||||
CommunicationPort(Id, bool, communication::PortMenuChoice),
|
||||
Resolve(Id, TransitionField, FieldDecision),
|
||||
Preview,
|
||||
}
|
||||
@@ -125,10 +127,12 @@ impl Relationship {
|
||||
return validation::can_create_interface_role(p, id);
|
||||
}
|
||||
if self.kind == RelationKind::ExchangeAllocation {
|
||||
return p
|
||||
.relations
|
||||
.get(&id)
|
||||
.is_some_and(|r| r.kind() == RelationKind::BoundaryExchange);
|
||||
return p.relations.get(&id).is_some_and(|r| {
|
||||
matches!(
|
||||
r.kind(),
|
||||
RelationKind::BoundaryExchange | RelationKind::CommunicationMean
|
||||
)
|
||||
});
|
||||
}
|
||||
p.elements.get(&id).is_some_and(|e| {
|
||||
Kind::ALL
|
||||
@@ -187,6 +191,10 @@ impl Relationship {
|
||||
format!("{} {verb} {}", p.named(source), p.named(target))
|
||||
}
|
||||
fn default_orientation(&mut self, p: &Project) {
|
||||
if self.kind == RelationKind::CommunicationMean {
|
||||
self.oriented = false;
|
||||
return;
|
||||
}
|
||||
self.oriented = !self
|
||||
.source
|
||||
.as_ref()
|
||||
@@ -230,8 +238,15 @@ impl Relationship {
|
||||
if let RelationBody::CapabilityExtend { condition, .. } = &mut body {
|
||||
*condition = self.condition.text();
|
||||
}
|
||||
if let RelationBody::BoundaryExchange { oriented, .. } = &mut body {
|
||||
if let RelationBody::BoundaryExchange {
|
||||
oriented, items, ..
|
||||
}
|
||||
| RelationBody::CommunicationMean {
|
||||
oriented, items, ..
|
||||
} = &mut body
|
||||
{
|
||||
*oriented = self.oriented;
|
||||
*items = self.items.clone();
|
||||
}
|
||||
let commands = vec![Command::CreateRelation(Relation {
|
||||
id,
|
||||
@@ -248,6 +263,7 @@ impl Relationship {
|
||||
pub struct Transition {
|
||||
pub request: TransitionRequest,
|
||||
pub plan: TransitionPlan,
|
||||
communication_ports: std::collections::BTreeMap<Id, communication::PortDraft>,
|
||||
}
|
||||
impl Workflow {
|
||||
pub fn manual_trace(p: &Project, selected: Id) -> Result<Self, String> {
|
||||
@@ -334,7 +350,11 @@ impl Workflow {
|
||||
let mut request = TransitionRequest::new(direction, vec![selected]);
|
||||
request.scope = DependencyScope::Required;
|
||||
let plan = plan_transition(p, &request).map_err(|e| e.to_string())?;
|
||||
Ok(Self::Transition(Box::new(Transition { request, plan })))
|
||||
Ok(Self::Transition(Box::new(Transition {
|
||||
request,
|
||||
plan,
|
||||
communication_ports: Default::default(),
|
||||
})))
|
||||
}
|
||||
/// Return a complete accepted candidate only on explicit Apply. Intermediate
|
||||
/// choices and previews never mutate the Session.
|
||||
@@ -439,6 +459,9 @@ impl Workflow {
|
||||
},
|
||||
Self::Transition(d) => {
|
||||
match event {
|
||||
Event::CommunicationPort(exchange, source, value) => {
|
||||
d.choose_communication_port(p, exchange, source, value)?;
|
||||
}
|
||||
Event::Scope(scope) => {
|
||||
d.request.scope = match scope.as_str() {
|
||||
"Required references" => DependencyScope::Required,
|
||||
@@ -546,6 +569,16 @@ impl Workflow {
|
||||
Event::Apply => {
|
||||
let mut candidate =
|
||||
apply_transition(p, &d.plan).map_err(|e| e.to_string())?;
|
||||
// Behavior is already usable in its dedicated workspace. An
|
||||
// unrequested architecture placement would alter an unrelated
|
||||
// view, including its routes, just to display this operation.
|
||||
if d.request.destination_diagram.is_none()
|
||||
&& d.request.sources.first().is_some_and(|source| {
|
||||
crate::behavior::selected_behavior(p, *source).is_some()
|
||||
})
|
||||
{
|
||||
return Ok(Some(candidate));
|
||||
}
|
||||
let layer = d.request.direction.target_layer();
|
||||
let diagram = d
|
||||
.request
|
||||
@@ -720,10 +753,13 @@ impl Workflow {
|
||||
.padding(9),
|
||||
);
|
||||
}
|
||||
if d.kind == RelationKind::BoundaryExchange {
|
||||
if matches!(
|
||||
d.kind,
|
||||
RelationKind::BoundaryExchange | RelationKind::CommunicationMean
|
||||
) {
|
||||
content = content.push(
|
||||
checkbox(d.oriented)
|
||||
.label("Oriented component exchange")
|
||||
.label("Directed source → target (unchecked: bidirectional)")
|
||||
.on_toggle(|v| Message::Workflow(Event::Oriented(v))),
|
||||
);
|
||||
}
|
||||
@@ -753,6 +789,14 @@ impl Workflow {
|
||||
.width(Fill),
|
||||
);
|
||||
}
|
||||
}
|
||||
if matches!(
|
||||
d.kind,
|
||||
RelationKind::FunctionalExchange
|
||||
| RelationKind::BoundaryExchange
|
||||
| RelationKind::CommunicationMean
|
||||
) {
|
||||
content = content.push(text("Declared carried items").size(14));
|
||||
for item in p
|
||||
.elements
|
||||
.values()
|
||||
@@ -905,6 +949,9 @@ impl Workflow {
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(ports) = d.communication_view(p, source) {
|
||||
item = item.push(ports);
|
||||
}
|
||||
content = content.push(
|
||||
iced::widget::container(item)
|
||||
.padding(12)
|
||||
|
||||
Reference in New Issue
Block a user