Merge pull request #4324 from nrq6993-a11y/stream/vc-feat3-g4-mixed-type-orientation

G4: Type orientation menu unchecked for mixed vertical/horizontal selection
This commit is contained in:
BFlat
2026-11-02 14:59:02 +07:00
committed by GitHub
3 changed files with 56 additions and 1 deletions
+1 -1
View File
@@ -38,7 +38,7 @@ pub fn checked(app: &VectorcraftApp, id: &str, p: &Value) -> Option<bool> {
};
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(),
+37
View File
@@ -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"));
@@ -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() {