Merge pull request #4184 from dotCooCoo/fix/character-direction-empty-caret

Character: Character Direction is off at a caret with no characters selected
This commit is contained in:
BFlat
2026-10-26 08:40:40 +07:00
committed by GitHub
+34 -2
View File
@@ -775,16 +775,18 @@ fn style_toggle(ui: &mut Ui, g: Glyph, tip: &str, on: bool) -> bool {
/// The Character Direction submenu: Default, Left to Right and Right to Left set the characters the
/// panel acts on ([`char_cmd`]) as the bidi algorithm sets them, or left to right or right to left
/// inside their paragraph. The direction those characters share is checked, and none is checked
/// when they differ.
/// when they differ. At a caret in text the Type tool edits, with no characters selected, the items
/// are disabled.
fn char_direction_items(app: &mut VectorcraftApp, ui: &mut Ui) {
use vectorcraft_doc::ParaDirection;
let direction = shared(app, |s| s.char_direction);
let enabled = text_editing(app).is_none_or(|(_, a, b)| b > a);
for (label, d, key) in [
(tl!("Default"), None, "default"),
(tl!("Left to Right"), Some(ParaDirection::LeftToRight), "leftToRight"),
(tl!("Right to Left"), Some(ParaDirection::RightToLeft), "rightToLeft"),
] {
if menu_item(ui, label, true, direction == Some(d)) {
if menu_item(ui, label, enabled, direction == Some(d)) {
format(app, json!({"charDirection": key}));
}
}
@@ -1437,6 +1439,36 @@ mod tests {
assert_eq!(checked(&mut app), ["Default"]);
}
/// At a caret in text the Type tool edits, with no characters selected, the Character
/// Direction items are disabled: a click on one leaves the direction of every character as it was.
#[test]
fn character_direction_does_nothing_at_an_empty_caret() {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.run("file.new", json!({"width": 300, "height": 200})).unwrap();
let id = app.run("text.create", json!({"x": 20, "y": 50, "text": "שלום 21 10 2026"})).unwrap()["id"].as_u64().unwrap();
app.run("select.set", json!({"ids": [id]})).unwrap();
app.select_tool("type");
app.session.apply_actions(vec![vectorcraft_tools::Action::Notify("text.editNew".into())]).unwrap();
app.session.set_tool_option("select", &json!({"start": 3, "end": 3}));
let directions = |app: &VectorcraftApp| match &app.session.active().unwrap().doc.node(NodeId(id)).unwrap().kind {
NodeKind::Text(t) => t.runs.iter().map(|r| (r.text.clone(), r.style.char_direction)).collect::<Vec<_>>(),
_ => panic!("text"),
};
let before = directions(&app);
let ctx = egui::Context::default();
let click_rtl = |app: &mut VectorcraftApp| {
let texts = super::super::tests_appearance::frame_events(&ctx, app, vec![], char_direction_items);
let at = texts.iter().find(|(t, _)| t.trim_start_matches(['✓', ' ']) == "Right to Left").unwrap_or_else(|| panic!("{texts:?}")).1;
super::super::tests_appearance::click(&ctx, app, at.center(), char_direction_items);
};
click_rtl(&mut app);
assert_eq!(directions(&app), before);
// With characters selected, the same click sets their direction.
app.session.set_tool_option("select", &json!({"start": 0, "end": 4}));
click_rtl(&mut app);
assert_ne!(directions(&app), before);
}
/// No Break is in the panel menu, and choosing it marks the selected characters.
#[test]
fn no_break_menu_item_toggles_the_selected_characters() {