diff --git a/crates/ui-egui/src/panels/properties.rs b/crates/ui-egui/src/panels/properties.rs index fdbcc2d89..49716e048 100644 --- a/crates/ui-egui/src/panels/properties.rs +++ b/crates/ui-egui/src/panels/properties.rs @@ -142,8 +142,16 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) { actions.push((tl!("Crop Image"), "ui.cropImage")); actions.push((tl!("Mask"), "object.maskImage")); } - actions.push((tl!("Offset Path"), "object.path.offsetPath")); - actions.push((tl!("Simplify"), "object.path.simplify")); + // Object › Path's Offset Path and Simplify take paths: type alone could only fail, and offsets + // live through the Appearance panel's Effect › Path › Offset Path (#2238). + let type_only = app.session.active().is_some_and(|st| { + let mut nodes = st.selection.objects.iter().filter_map(|id| st.doc.node(*id)); + nodes.all(|n| matches!(n.kind, NodeKind::Text(_))) + }); + if !type_only { + actions.push((tl!("Offset Path"), "object.path.offsetPath")); + actions.push((tl!("Simplify"), "object.path.simplify")); + } actions.push((tl!("Arrange: Bring to Front"), "object.arrange.bringToFront")); actions.push((tl!("Lock"), "object.lock")); // Lock and Isolate Group are left out while their commands are off (in isolation mode, while diff --git a/crates/ui-egui/src/panels/properties/tests.rs b/crates/ui-egui/src/panels/properties/tests.rs index 1cfa6c380..7bf2e6d15 100644 --- a/crates/ui-egui/src/panels/properties/tests.rs +++ b/crates/ui-egui/src/panels/properties/tests.rs @@ -1647,3 +1647,19 @@ fn selected_guides_show_their_position_in_a_transform_section() { let texts: Vec = frame(&mut app, &ctx, vec![]).into_iter().map(|(t, _)| t).collect(); assert!(!texts.iter().any(|t| t == "Guides") && texts.iter().any(|t| t == "W:"), "{texts:?}"); } + +/// #2238: Object › Path's Offset Path and Simplify take paths, so they aren't Quick Actions for +/// type alone, where they could only fail ("select paths"); live type offsets through the +/// Appearance panel's Effect › Path › Offset Path. A path, also with type, still has them. +#[test] +fn offset_path_and_simplify_are_not_quick_actions_for_type_alone() { + let mut app = new_app(); + let t = app.run("text.create", json!({"x": 50, "y": 200, "text": "Hi"})).unwrap()["id"].clone(); + let ctx = egui::Context::default(); + let texts = tall(&mut app, &ctx, vec![]); + assert!(!shows(&texts, "Offset Path") && !shows(&texts, "Simplify") && shows(&texts, "Lock"), "type: {texts:?}"); + let r = rect(&mut app, 20.0, 20.0, 40.0, 40.0); + app.run("select.set", json!({"ids": [t, r]})).unwrap(); + let texts = tall(&mut app, &ctx, vec![]); + assert!(shows(&texts, "Offset Path") && shows(&texts, "Simplify"), "type and a path: {texts:?}"); +}