Integrate scoped reference chooser and scenario form focus and reveal

This commit is contained in:
Codex
2026-09-11 06:24:20 -07:00
parent c7ed894900
commit 7f081ad457
27 changed files with 4544 additions and 79 deletions
@@ -1,7 +1,9 @@
//! Scenario presentation. Layout/camera controls never construct model commands.
use super::super::scenario_scroll;
use super::*;
use iced::widget::{Space, column, sensor};
use iced::widget::{Space, column, keyed_column, sensor};
pub(crate) const NAME_INPUT: &str = "scenario-form-name";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Shelf {
@@ -82,10 +84,21 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a
// The outline is a sibling shelf, not an ancestor of this canvas.
scene.scroll_offset = state.scroll_offset();
scene.pending_placement = state.pending_placement(owner);
let reveal = state.form_session().and_then(|token| {
let (slot, _) = scene.pending_placement?;
let marker = scene.slots.iter().find(|marker| marker.slot == slot)?;
Some(ScrollReveal {
token,
slot,
y: marker.y * scale,
padding: (24. * scale).max(12.),
})
});
let size = Size::new(scene.size.width * scale, scene.size.height * scale);
let canvas = canvas_pane(
context,
state.scroll_restore(context, ScrollArea::Canvas),
reveal,
canvas::Canvas::new(scene)
.width(size.width)
.height(size.height)
@@ -287,7 +300,11 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a
presentation.shelf.is_some(),
pending,
);
let mut form_panel = editor_panel(Space::new().height(0).into(), Space::new().height(0).into());
let mut form_panel = editor_panel(
Id::nil(),
Space::new().height(0).into(),
Space::new().height(0).into(),
);
if let Some(d) = app
.behavior
.scenario
@@ -298,6 +315,7 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a
let mut form = column![
text(d.tool.label()).size(16),
text_input("Name (defaults to selected source)", &d.name)
.id(NAME_INPUT)
.on_input(|s| event(Event::Name(s)))
.padding(9)
.size(12)
@@ -560,7 +578,11 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a
action("Cancel", event(Event::Cancel))
]
.spacing(7);
form_panel = editor_panel(footer.into(), form.into());
let session = state.form_session().expect("visible scenario draft");
form_panel = sensor(editor_panel(session, footer.into(), form.into()))
.key(session)
.on_show(move |_| Message::ScenarioCanvas(CanvasEvent::FormShown(context, session)))
.into();
}
workspace_layout(header.into(), details, canvas, form_panel, pending)
}
@@ -633,13 +655,14 @@ fn details_pane<'a, R: iced::advanced::text::Renderer + 'a>(
fn canvas_pane<'a, R: iced::advanced::text::Renderer + 'a>(
context: Context,
restore: Option<ScrollRestore>,
reveal: Option<ScrollReveal>,
content: iced::Element<'a, Message, Theme, R>,
) -> iced::Element<'a, Message, Theme, R> {
container(
sensor(scenario_scroll::observe(
sensor(scenario_scroll::observe_canvas(
context,
ScrollArea::Canvas,
restore,
reveal,
scrollable(content)
.id("scenario-canvas")
.direction(scrollable::Direction::Both {
@@ -661,16 +684,23 @@ fn canvas_pane<'a, R: iced::advanced::text::Renderer + 'a>(
}
fn editor_panel<'a, R: iced::advanced::text::Renderer + 'a>(
session: Id,
actions: iced::Element<'a, Message, Theme, R>,
fields: iced::Element<'a, Message, Theme, R>,
) -> iced::Element<'a, Message, Theme, R> {
container(
column![
container(actions).id("scenario-actions").width(Fill),
scrollable(fields)
.id("scenario-form")
.width(Fill)
.height(Fill),
keyed_column([(
session,
scrollable(fields)
.id("scenario-form")
.width(Fill)
.height(Fill)
.into(),
)])
.width(Fill)
.height(Fill),
]
.spacing(6),
)