From b25065c442fd8decd3419a94d33125cafbf9a22e Mon Sep 17 00:00:00 2001 From: "sorokin.oleg.edu" Date: Sat, 12 Sep 2026 07:06:09 -0700 Subject: [PATCH] Remove misleading canvas activation controls --- .../src/behavior/canvas_workspace.rs | 13 +++---- .../src/behavior/canvas_workspace/tests.rs | 2 +- .../src/behavior/scenario/workspace.rs | 35 +------------------ .../src/behavior/scenario/workspace/tests.rs | 19 +++++++--- .../src/behavior/topology/layout_tests.rs | 19 +++++++--- .../oa-desktop/src/behavior/topology/view.rs | 35 +------------------ 6 files changed, 40 insertions(+), 83 deletions(-) diff --git a/crates/oa-desktop/src/behavior/canvas_workspace.rs b/crates/oa-desktop/src/behavior/canvas_workspace.rs index b95ab5bf..671f87e5 100644 --- a/crates/oa-desktop/src/behavior/canvas_workspace.rs +++ b/crates/oa-desktop/src/behavior/canvas_workspace.rs @@ -29,7 +29,6 @@ pub fn controls<'a>( keyboard: bool, scale: f32, details: Message, - focus: Option, zoom: impl Fn(Option) -> Message, publish: impl Fn(Event) -> Message + Copy + 'a, ) -> Element<'a, Message> { @@ -46,17 +45,19 @@ pub fn controls<'a>( publish, ) }; - row![ + let controls = row![ control("Details", "Details", Some(details)), - tooltip(control("Canvas", "Canvas", focus), - container(text("F6: enter/leave canvas controls · Tab: next · Enter/Space: activate · Esc: leave").size(12)).padding(7).style(crate::style::card), - tooltip::Position::Bottom), control("Fit", "Fit", Some(zoom(None))), control("ZoomOut", "−", Some(zoom(Some(scale / 1.25)))), text(format!("{:.0}%", scale * 100.)).size(12), control("ZoomIn", "+", Some(zoom(Some(scale * 1.25)))), control("ActualSize", "100%", Some(zoom(Some(1.)))), - ].spacing(4).align_y(iced::Center).into() + ].spacing(4).align_y(iced::Center); + tooltip( + controls, + container(text("F6: enter/leave canvas keyboard controls · Tab: next · Enter/Space: activate · Esc: leave").size(12)).padding(7).style(crate::style::card), + tooltip::Position::Bottom, + ).into() } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/crates/oa-desktop/src/behavior/canvas_workspace/tests.rs b/crates/oa-desktop/src/behavior/canvas_workspace/tests.rs index afc84101..b9d9649d 100644 --- a/crates/oa-desktop/src/behavior/canvas_workspace/tests.rs +++ b/crates/oa-desktop/src/behavior/canvas_workspace/tests.rs @@ -628,7 +628,7 @@ pub(crate) async fn retained_toolbar_boundaries( use iced::keyboard::key::Named; for boundary in ["Chooser", "Dirty", "Picker"] { let mut packets = vec![]; - for name in ["Fit", tool, "Details", "Panels", "Canvas"] { + for name in ["Fit", tool, "Details"] { packets.push(capture_toolbar(mounted, app, name)); } let lifetime = app.camera_epoch; diff --git a/crates/oa-desktop/src/behavior/scenario/workspace.rs b/crates/oa-desktop/src/behavior/scenario/workspace.rs index d4d08d7b..dd4c1d3f 100644 --- a/crates/oa-desktop/src/behavior/scenario/workspace.rs +++ b/crates/oa-desktop/src/behavior/scenario/workspace.rs @@ -106,35 +106,7 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a .height(Fill) .style(style::card) .into(); - let mut navigation = row![ - out.width(Fill), - super::super::canvas_workspace::Control::new( - button( - text(if presentation.focused { - "Restore panels" - } else { - "Focus canvas" - }) - .size(12) - ) - .padding(6) - .on_press(super::super::canvas_workspace::intent( - scope, - "Panels", - Message::ScenarioCanvas(CanvasEvent::Focus(context)) - )), - scope, - "Panels", - keyboard, - Some(super::super::canvas_workspace::intent( - scope, - "Panels", - Message::ScenarioCanvas(CanvasEvent::Focus(context)) - )), - camera - ) - ] - .spacing(6); + let mut navigation = row![out.width(Fill)].spacing(6); if state.can_back(p, context) { navigation = navigation.push(button(text("Back").size(12)).padding(6).on_press_maybe( @@ -148,11 +120,6 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a keyboard, scale, Message::ScenarioCanvas(CanvasEvent::Shelf(context, Shelf::Selection)), - clean.then_some(Message::ScenarioCanvas(CanvasEvent::Camera( - context, - scope.epoch, - super::super::canvas_workspace::Event::Focus - ))), move |zoom| Message::ScenarioCanvas(CanvasEvent::Zoom(context, zoom)), camera ) diff --git a/crates/oa-desktop/src/behavior/scenario/workspace/tests.rs b/crates/oa-desktop/src/behavior/scenario/workspace/tests.rs index 311c93cb..11a96c98 100644 --- a/crates/oa-desktop/src/behavior/scenario/workspace/tests.rs +++ b/crates/oa-desktop/src/behavior/scenario/workspace/tests.rs @@ -12,6 +12,15 @@ async fn production_scenario_canvas_keeps_bounds_draft_identity_and_camera_throu let _ = app.update(Message::Page(crate::app::Page::Behavior)); app.window_size = Size::new(1100., 700.); let mut mounted = Mounted::new(&mut app).await; + let geometry = mounted.geometry(&app); + let scope = canvas_workspace::tests::scope(&app); + for removed in ["Canvas", "Panels"] { + assert!(!geometry.containers.contains_key(&scope.control_id(removed))); + } + assert!( + !canvas_workspace::tests::focused(&mut mounted, &app, "viewport"), + "direct editing needs no activation or initial keyboard focus grab" + ); for size in [Size::new(1100., 700.), Size::new(1440., 900.)] { app.window_size = size; mounted.settle(&mut app).await; @@ -1362,6 +1371,11 @@ async fn production_scenario_camera_external_controls_bounds_and_retained_deltas let size = Size::new(app.window_size.width + 90., app.window_size.height + 35.); let task = app.update(Message::WindowResized(size)); mounted.perform(&mut app, task).await; + } else if boundary == "Panels" { + // Panel layout remains a presentation command, not canvas activation. + let context = app.scenario_context().unwrap(); + let task = app.update(Message::ScenarioCanvas(CanvasEvent::Focus(context))); + mounted.perform(&mut app, task).await; } else { let id = scope(&app).control_id(boundary); let at = mounted.geometry(&app).containers[&id].center(); @@ -1531,10 +1545,7 @@ async fn production_scenario_keyboard_enters_activates_draws_focus_and_returns_t ))); assert_eq!(app.behavior.scenario.presentation.pan, iced::Vector::ZERO); assert!(focused(&mut mounted, &app, "Fit")); - tab_to(&mut mounted, &mut app, "Canvas").await; - mounted - .batch(&mut app, &[key(Named::Enter)], mouse::Cursor::Unavailable) - .await; + tab_to(&mut mounted, &mut app, "viewport").await; assert!(focused(&mut mounted, &app, "viewport")); mounted .batch(&mut app, &[key(Named::Escape)], mouse::Cursor::Unavailable) diff --git a/crates/oa-desktop/src/behavior/topology/layout_tests.rs b/crates/oa-desktop/src/behavior/topology/layout_tests.rs index dee7929b..9a3c92ed 100644 --- a/crates/oa-desktop/src/behavior/topology/layout_tests.rs +++ b/crates/oa-desktop/src/behavior/topology/layout_tests.rs @@ -18,6 +18,15 @@ async fn production_process_canvas_scaled_path_creation_preserves_source_and_edi let _ = app.update(Message::Page(crate::app::Page::Behavior)); app.window_size = size; mounted.settle(&mut app).await; + let geometry = mounted.geometry(&app); + let scope = canvas_workspace::tests::scope(&app); + for removed in ["Canvas", "Panels"] { + assert!(!geometry.containers.contains_key(&scope.control_id(removed))); + } + assert!( + !canvas_workspace::tests::focused(&mut mounted, &app, "viewport"), + "direct editing needs no activation or initial keyboard focus grab" + ); for scale in [0.5, 1., 2.] { let context = app.topology_context().unwrap(); let _ = app.update(Message::TopologyCanvas(CanvasEvent::Zoom( @@ -239,6 +248,11 @@ async fn production_process_camera_external_controls_bounds_and_retained_deltas_ let size = Size::new(app.window_size.width + 90., app.window_size.height + 35.); let task = app.update(Message::WindowResized(size)); mounted.perform(&mut app, task).await; + } else if boundary == "Panels" { + // Panel layout remains a presentation command, not canvas activation. + let context = app.topology_context().unwrap(); + let task = app.update(Message::TopologyCanvas(CanvasEvent::Focus(context))); + mounted.perform(&mut app, task).await; } else { let id = scope(&app).control_id(boundary); let at = mounted.geometry(&app).containers[&id].center(); @@ -399,10 +413,7 @@ async fn production_process_keyboard_enters_activates_draws_focus_and_returns_to ))); assert_eq!(app.behavior.topology.pan, iced::Vector::ZERO); assert!(focused(&mut mounted, &app, "Fit")); - tab_to(&mut mounted, &mut app, "Canvas").await; - mounted - .batch(&mut app, &[key(Named::Enter)], mouse::Cursor::Unavailable) - .await; + tab_to(&mut mounted, &mut app, "viewport").await; assert!(focused(&mut mounted, &app, "viewport")); mounted .batch(&mut app, &[key(Named::Escape)], mouse::Cursor::Unavailable) diff --git a/crates/oa-desktop/src/behavior/topology/view.rs b/crates/oa-desktop/src/behavior/topology/view.rs index 4302d849..7fe6fbcc 100644 --- a/crates/oa-desktop/src/behavior/topology/view.rs +++ b/crates/oa-desktop/src/behavior/topology/view.rs @@ -221,45 +221,12 @@ pub(super) fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Ele .style(style::card) .into(); let header = column![ - row![ - out.width(Fill), - super::super::canvas_workspace::Control::new( - button( - text(if state.focused { - "Restore panels" - } else { - "Focus canvas" - }) - .size(12) - ) - .padding(6) - .on_press(super::super::canvas_workspace::intent( - scope, - "Panels", - Message::TopologyCanvas(CanvasEvent::Focus(context)) - )), - scope, - "Panels", - keyboard, - Some(super::super::canvas_workspace::intent( - scope, - "Panels", - Message::TopologyCanvas(CanvasEvent::Focus(context)) - )), - camera - ) - ] - .spacing(6), + out.width(Fill), super::super::canvas_workspace::controls( scope, keyboard, scale, event(Event::Shelf(Shelf::Selection)), - clean.then_some(Message::TopologyCanvas(CanvasEvent::Camera( - context, - scope.epoch, - super::super::canvas_workspace::Event::Focus - ))), move |zoom| Message::TopologyCanvas(CanvasEvent::Zoom(context, zoom)), camera )