Integrate allocation drag candidate with guarded input and atomic history

This commit is contained in:
2026-09-12 03:47:45 -07:00
parent 0bd7886608
commit f52d81c1b9
19 changed files with 5067 additions and 20 deletions
+41 -7
View File
@@ -284,7 +284,7 @@ pub fn view(app: &App) -> View<'_, Message> {
)
.padding([4, 16])
.style(style::panel);
let root: View<'_, Message> = column![header, task_nav, body, footer].into();
let root = crate::allocation_input::root(app, column![header, task_nav, body, footer]);
if app.architecture.as_ref().is_some_and(|s| s.modal()) {
return modal_width(
root,
@@ -414,7 +414,7 @@ fn diagram(app: &App) -> View<'_, Message> {
.align_y(iced::Center);
if let Some(id) = app.active_diagram {
chooser = chooser.push(action("View properties", Message::Select(id)));
controls = controls.push(action("Arrange", Message::Command(Command::Layout(id))));
controls = controls.push(action("Auto-layout", Message::Command(Command::Layout(id))));
}
let toolbar = column![chooser, controls].spacing(6);
let projection = app
@@ -442,6 +442,7 @@ fn diagram(app: &App) -> View<'_, Message> {
.align_y(iced::Center);
let canvas: View<'_, Message> = if let Some(id) = app.active_diagram {
let program = DiagramCanvas {
allocation: Some(app.allocation_capability()),
project: app.project(),
view_index: Some(app.document.view_index()),
diagram: id,
@@ -462,14 +463,22 @@ fn diagram(app: &App) -> View<'_, Message> {
widget::canvas(crate::diagram::PortLabels(program))
.width(Fill)
.height(Fill),
widget::canvas(crate::diagram::WorkFeedback(program))
.width(Fill)
.height(Fill),
];
if let Some(editor) = crate::app::architecture_authoring::inline_editor(app) {
scene = scene.push(editor);
}
row![
widget::sensor(scene)
.on_show(Message::CanvasResized)
.on_resize(Message::CanvasResized),
widget::sensor(
container(scene)
.id(crate::allocation_input::CANVAS_ID)
.width(Fill)
.height(Fill)
)
.on_show(Message::CanvasResized)
.on_resize(Message::CanvasResized),
crate::app::architecture_authoring::palette(app)
]
.height(Fill)
@@ -500,6 +509,27 @@ fn diagram(app: &App) -> View<'_, Message> {
if app.active_diagram.is_some() {
tools = tools.push(modes);
}
if projection == Some(ProjectionKind::Allocation) {
tools = tools.push(
row![
action(
&format!(
"{} · {}",
if app.allocation_drag.arrange_next {
"Arrange next drag: armed"
} else {
"Arrange next drag"
},
crate::allocation_input::ARRANGE_SHORTCUT
),
Message::WorkDrag(crate::app::allocation_drag::Event::ArrangeNext)
),
label("Drag work into a performer to assign · out to remove assignment")
]
.spacing(8)
.align_y(iced::Center),
);
}
if let Some(diagram) = app.active_diagram {
let view = oa_core::projection::project_view(app.project(), diagram);
let edge = view.edges.iter().find(|edge| edge.id == app.selected);
@@ -511,7 +541,9 @@ fn diagram(app: &App) -> View<'_, Message> {
)
.is_some_and(|(source, target)| source != edge.source || target != edge.target)
});
let hint = if let Some(session) = &app.connection {
let hint = if let Some(feedback) = &app.allocation_drag.feedback {
feedback.text.as_str()
} else if let Some(session) = &app.connection {
if session.source.is_some() {
if session.candidates.is_empty() {
"No compatible targets are visible. Expand containers or show an endpoint · Esc cancels"
@@ -528,7 +560,9 @@ fn diagram(app: &App) -> View<'_, Message> {
} else {
"Right-click for actions · drag to arrange · scroll to zoom"
};
tools = tools.push(container(label(hint)).height(30));
// Status is outside the measured canvas. Clipping prevents long text
// from painting over work headers or frozen target labels below it.
tools = tools.push(container(label(hint)).height(30).width(Fill).clip(true));
}
column![container(tools).padding(14), canvas].into()
}