diff --git a/crates/ui-egui/src/menus/state.rs b/crates/ui-egui/src/menus/state.rs index a072a7622..26904fcae 100644 --- a/crates/ui-egui/src/menus/state.rs +++ b/crates/ui-egui/src/menus/state.rs @@ -38,7 +38,7 @@ pub fn checked(app: &VectorcraftApp, id: &str, p: &Value) -> Option { }; Some(match id { "type.orientation.vertical" | "type.orientation.horizontal" => { - selected_text(false).is_some_and(|t| t.vertical == (id == "type.orientation.vertical")) + crate::panels::character::shared_text_flag(app, |t| t.vertical) == Some(id == "type.orientation.vertical") } "type.opticalMarginAlignment" => crate::panels::character::shared_text_flag(app, |t| t.optical_margin) == Some(true), "view.outline" => app.outline_view(), diff --git a/crates/ui-egui/src/menus/tests.rs b/crates/ui-egui/src/menus/tests.rs index 046639b94..a9dd3f749 100644 --- a/crates/ui-egui/src/menus/tests.rs +++ b/crates/ui-egui/src/menus/tests.rs @@ -255,6 +255,43 @@ fn optical_margin_alignment_menu_unchecked_when_shared_flag_none() { assert_eq!(checked(&app, id, &Value::Null), Some(true)); } +/// Type › Orientation menu checks use `shared_text_flag`; mixed values leave both unchecked. +#[test] +fn type_orientation_menu_unchecked_when_shared_vertical_none() { + let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), crate::Services::default()); + app.run("file.new", json!({})).unwrap(); + let h = app.run("text.create", json!({"x": 10, "y": 40, "text": "H"})).unwrap()["id"].clone(); + let v = app.run("text.create", json!({"x": 10, "y": 80, "text": "V", "vertical": true})).unwrap()["id"].clone(); + app.run("select.set", json!({"ids": [h, v]})).unwrap(); + assert_eq!(crate::panels::character::shared_text_flag(&app, |t| t.vertical), None); + assert_eq!(checked(&app, "type.orientation.vertical", &Value::Null), Some(false)); + assert_eq!(checked(&app, "type.orientation.horizontal", &Value::Null), Some(false)); + app.run("select.set", json!({"ids": [v]})).unwrap(); + assert_eq!(checked(&app, "type.orientation.vertical", &Value::Null), Some(true)); + assert_eq!(checked(&app, "type.orientation.horizontal", &Value::Null), Some(false)); +} + +#[test] +fn type_orientation_menu_unchecked_for_three_object_mixed_selections() { + let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), crate::Services::default()); + app.run("file.new", json!({})).unwrap(); + let v0 = app.run("text.create", json!({"x": 10, "y": 40, "text": "v0", "vertical": true})).unwrap()["id"].clone(); + let h1 = app.run("text.create", json!({"x": 10, "y": 80, "text": "h1"})).unwrap()["id"].clone(); + let h2 = app.run("text.create", json!({"x": 10, "y": 120, "text": "h2"})).unwrap()["id"].clone(); + app.run("select.set", json!({"ids": [v0.clone(), h1.clone(), h2.clone()]})).unwrap(); + assert_eq!(checked(&app, "type.orientation.vertical", &Value::Null), Some(false)); + assert_eq!(checked(&app, "type.orientation.horizontal", &Value::Null), Some(false)); + let h0 = app.run("text.create", json!({"x": 10, "y": 160, "text": "h0"})).unwrap()["id"].clone(); + let v1 = app.run("text.create", json!({"x": 10, "y": 200, "text": "v1", "vertical": true})).unwrap()["id"].clone(); + let v2 = app.run("text.create", json!({"x": 10, "y": 240, "text": "v2", "vertical": true})).unwrap()["id"].clone(); + app.run("select.set", json!({"ids": [h0.clone(), v1.clone(), v2.clone()]})).unwrap(); + assert_eq!(checked(&app, "type.orientation.vertical", &Value::Null), Some(false)); + assert_eq!(checked(&app, "type.orientation.horizontal", &Value::Null), Some(false)); + app.run("select.set", json!({"ids": [v0.clone(), v1.clone(), v2.clone()]})).unwrap(); + assert_eq!(checked(&app, "type.orientation.vertical", &Value::Null), Some(true)); + assert_eq!(checked(&app, "type.orientation.horizontal", &Value::Null), Some(false)); +} + #[test] fn panel_ids_are_case_insensitive_and_labels_work() { assert_eq!(normalize_panel("layers"), Some("layers")); diff --git a/crates/ui-egui/src/panels/character/tests.rs b/crates/ui-egui/src/panels/character/tests.rs index d9c419f12..5775fbdc5 100644 --- a/crates/ui-egui/src/panels/character/tests.rs +++ b/crates/ui-egui/src/panels/character/tests.rs @@ -807,6 +807,24 @@ fn shared_text_flag_optical_margin_three_object_selections() { assert_eq!(shared_text_flag(&app, |t| t.optical_margin), Some(true)); } +#[test] +fn shared_text_flag_vertical_three_object_selections() { + let mut app = VectorcraftApp::new(Session::new(), Default::default()); + app.run("file.new", json!({})).unwrap(); + let v0 = app.run("text.create", json!({"x": 10, "y": 40, "text": "v0", "vertical": true})).unwrap()["id"].clone(); + let h1 = app.run("text.create", json!({"x": 10, "y": 80, "text": "h1"})).unwrap()["id"].clone(); + let h2 = app.run("text.create", json!({"x": 10, "y": 120, "text": "h2"})).unwrap()["id"].clone(); + app.run("select.set", json!({"ids": [v0.clone(), h1.clone(), h2.clone()]})).unwrap(); + assert_eq!(shared_text_flag(&app, |t| t.vertical), None); + let h0 = app.run("text.create", json!({"x": 10, "y": 160, "text": "h0"})).unwrap()["id"].clone(); + let v1 = app.run("text.create", json!({"x": 10, "y": 200, "text": "v1", "vertical": true})).unwrap()["id"].clone(); + let v2 = app.run("text.create", json!({"x": 10, "y": 240, "text": "v2", "vertical": true})).unwrap()["id"].clone(); + app.run("select.set", json!({"ids": [h0.clone(), v1.clone(), v2.clone()]})).unwrap(); + assert_eq!(shared_text_flag(&app, |t| t.vertical), None); + app.run("select.set", json!({"ids": [v0.clone(), v1.clone(), v2.clone()]})).unwrap(); + assert_eq!(shared_text_flag(&app, |t| t.vertical), Some(true)); +} + /// Small Caps, Superscript and Subscript buttons and menu items stay off when the selection mixes them. #[test] fn character_mixed_small_caps_and_position_show_off() {