Character: Character Direction is off at a caret with no characters selected

With the Type tool at a caret and no characters selected, choosing an
item in the Character panel menu's Character Direction submenu set the
direction of every character in the type object. The three items are now
disabled until characters are selected.
This commit is contained in:
dotCooCoo
2026-10-26 08:18:23 +07:00
committed by bflatastic
parent ab821a776b
commit bb45038617
+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() {