diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index 63be7b2d8..984412702 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -3003,6 +3003,7 @@ font-technology Variable Променливи Single Quotes: Единични кавички: Single Right Quotation Mark Дясна единична кавичка Single-line Composer Ред по ред композитор + Toggle Line Composer Превключване на композитора на редове Sixth Space Шесто разстояние Size Размер Size Tile to Art Оразмеряване на плочката според обектите diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 8cf9280c4..73c1d312a 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -1825,6 +1825,7 @@ lighting Light Světlo Roman Hanging Punctuation Visící latinková interpunkce Select a text object to edit its paragraph attributes. Vyberte textový objekt, abyste mohli upravit atributy jeho odstavce. Single-line Composer Sazba jednoho řádku + Toggle Line Composer Přepnout sazbu řádků Space After Paragraph Mezera za odstavcem Space Before Paragraph Mezera před odstavcem Top-to-Top Leading Proklad od horní k horní diff --git a/crates/ui-egui/src/i18n/da.tsv b/crates/ui-egui/src/i18n/da.tsv index 2358aef32..bc891b84b 100644 --- a/crates/ui-egui/src/i18n/da.tsv +++ b/crates/ui-egui/src/i18n/da.tsv @@ -1637,6 +1637,7 @@ lighting Light Lys Roman Hanging Punctuation Romersk hængende tegnsætning Select a text object to edit its paragraph attributes. Markér et tekstobjekt for at redigere dets afsnitsattributter. Single-line Composer Enlinjesætter + Toggle Line Composer Skift linjesætter Space After Paragraph Mellemrum efter afsnit Space Before Paragraph Mellemrum før afsnit Top-to-Top Leading Linjeafstand top til top diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index f16b25dab..6bb0bdda2 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -3040,6 +3040,7 @@ mark-style Japanese Japanisch Single Quotes: Einfache Anführungszeichen: Single Right Quotation Mark Einfaches schließendes Anführungszeichen Single-line Composer Einzeilen-Setzer + Toggle Line Composer Zeilensetzer umschalten Sixth Space Sechstelgeviert-Leerzeichen Size Größe Size Tile to Art Kachelgröße an Grafik anpassen diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index e0036e678..9dff89a69 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -3484,6 +3484,7 @@ theme Appearance Εμφάνιση Single Quotes: Μονά εισαγωγικά: Single Right Quotation Mark Μονό δεξί εισαγωγικό Single-line Composer Σύνθεση μονής γραμμής + Toggle Line Composer Εναλλαγή σύνθεσης γραμμών Sixth Space Διάστημα ενός έκτου Size Tile to Art Προσαρμογή μεγέθους πλακιδίου στο σχέδιο Size/Leading Μέγεθος/διάστιχο diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index c8152a3f3..2e4156ba2 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -3075,6 +3075,7 @@ font-technology Variable Variables Single Quotes: Comillas simples: Single Right Quotation Mark Comilla simple de cierre Single-line Composer Composición de una línea + Toggle Line Composer Alternar composición de líneas Sixth Space Sexto de espacio Size Tamaño Size Tile to Art Ajustar tamaño del mosaico a la ilustración diff --git a/crates/ui-egui/src/i18n/fi.tsv b/crates/ui-egui/src/i18n/fi.tsv index c3dffe8ec..2abb500b1 100644 --- a/crates/ui-egui/src/i18n/fi.tsv +++ b/crates/ui-egui/src/i18n/fi.tsv @@ -1787,6 +1787,7 @@ lighting Light Valo Roman Hanging Punctuation Latinalaiset riippuvat välimerkit Select a text object to edit its paragraph attributes. Valitse tekstiobjekti, jonka kappalemääritteitä haluat muokata. Single-line Composer Yhden rivin asettelu + Toggle Line Composer Vaihda rivien asettelu Space After Paragraph Väli kappaleen jälkeen Space Before Paragraph Väli ennen kappaletta Top-to-Top Leading Riviväli yläreunasta yläreunaan diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index bbae03ed5..a6d75df4d 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -3072,6 +3072,7 @@ font-technology Variable Variables Single Quotes: Guillemets simples : Single Right Quotation Mark Guillemet simple fermant Single-line Composer Compositeur ligne par ligne + Toggle Line Composer Basculer le compositeur de lignes Sixth Space Espace d’un sixième Size Taille Size Tile to Art Ajuster le carreau à l’illustration diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index e34d5c8d5..33414fce7 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -3705,6 +3705,7 @@ mark-style Japanese Japán Single Quotes: Szimpla idézőjelek: Single Right Quotation Mark Jobb oldali szimpla idézőjel Single-line Composer Egysoros tördelő + Toggle Line Composer Sortördelő váltása Sixth Space Hatodkvirt-szóköz Size Méret Size Tile to Art Csempe méretezése a grafikához diff --git a/crates/ui-egui/src/i18n/id.tsv b/crates/ui-egui/src/i18n/id.tsv index eb2c01389..f9bff04fd 100644 --- a/crates/ui-egui/src/i18n/id.tsv +++ b/crates/ui-egui/src/i18n/id.tsv @@ -1637,6 +1637,7 @@ lighting Light Cahaya Roman Hanging Punctuation Tanda baca gantung Romawi Select a text object to edit its paragraph attributes. Pilih objek teks untuk mengedit atribut paragrafnya. Single-line Composer Komposer satu baris + Toggle Line Composer Alihkan komposer baris Space After Paragraph Spasi setelah paragraf Space Before Paragraph Spasi sebelum paragraf Top-to-Top Leading Leading dari atas ke atas diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index a3c015e4d..b0e060bbe 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -3109,6 +3109,7 @@ mark-style Japanese Giapponese Single Quotes: Virgolette singole: Single Right Quotation Mark Virgoletta singola di chiusura Single-line Composer Composizione su riga singola + Toggle Line Composer Alterna composizione delle righe Sixth Space Spazio di un sesto Size Dimensione Size Tile to Art Adatta tassello alla grafica diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index 15af584c3..07b58b7a0 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -2905,6 +2905,7 @@ mark-style Japanese 日本式 Simulate Paper 紙色をシミュレート Single Quotes: 一重引用符: Single-line Composer 1 行ずつ組む + Toggle Line Composer 行の組版方式を切り替え Size Tile to Art タイルをアートワークのサイズに合わせる Size/Leading サイズ/行送り Size: サイズ: diff --git a/crates/ui-egui/src/i18n/ka.tsv b/crates/ui-egui/src/i18n/ka.tsv index 1a2adecdb..0c0e47a53 100644 --- a/crates/ui-egui/src/i18n/ka.tsv +++ b/crates/ui-egui/src/i18n/ka.tsv @@ -1540,6 +1540,7 @@ lighting Light სინათლე Roman Hanging Punctuation ლათინური გამოწეული პუნქტუაცია Select a text object to edit its paragraph attributes. აბზაცის ატრიბუტების რედაქტირებისთვის მონიშნეთ ტექსტური ობიექტი. Single-line Composer სტრიქონის მიხედვით აწყობა + Toggle Line Composer აწყობის რეჟიმის გადართვა Space After Paragraph ინტერვალი აბზაცის შემდეგ Space Before Paragraph ინტერვალი აბზაცის წინ Top-to-Top Leading სტრიქონთა დაშორება ზედა კიდიდან ზედა კიდემდე diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index 5225910eb..67ec8582d 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -2899,6 +2899,7 @@ mark-style Japanese 일본식 Simulate Paper 용지 시뮬레이션 Single Quotes: 작은따옴표: Single-line Composer 한 줄 조판 + Toggle Line Composer 줄 조판 방식 전환 Size Tile to Art 타일을 아트웍 크기에 맞춤 Size/Leading 크기/행간 Size: 크기: diff --git a/crates/ui-egui/src/i18n/nl.tsv b/crates/ui-egui/src/i18n/nl.tsv index 04410cdca..92f855cb7 100644 --- a/crates/ui-egui/src/i18n/nl.tsv +++ b/crates/ui-egui/src/i18n/nl.tsv @@ -1651,6 +1651,7 @@ lighting Light Licht Roman Hanging Punctuation Romeinse hangende leestekens Select a text object to edit its paragraph attributes. Selecteer een tekstobject om de alineakenmerken ervan te bewerken. Single-line Composer Compositie per regel + Toggle Line Composer Compositiemethode wisselen Space After Paragraph Ruimte na alinea Space Before Paragraph Ruimte voor alinea Top-to-Top Leading Regelafstand van boven naar boven diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index 3c459fe4e..d218fa7c6 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -1745,6 +1745,7 @@ lighting Light Światło Roman Hanging Punctuation Wysunięta interpunkcja łacińska Select a text object to edit its paragraph attributes. Zaznacz obiekt tekstowy, aby edytować atrybuty akapitu. Single-line Composer Kompozytor jednowierszowy + Toggle Line Composer Przełącz kompozytor wierszy Space After Paragraph Odstęp po akapicie Space Before Paragraph Odstęp przed akapitem Top-to-Top Leading Interlinia od góry do góry diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index 59343e3a3..2cfdcfc2f 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -2552,6 +2552,7 @@ Single Quotes: Aspas Simples: Single Right Quotation Mark Aspa Direita Única Single-line Composer Compositor de Linha Única + Toggle Line Composer Alternar Compositor de Linhas Sixth Space Espaço de Sexto Size Tamanho Size Tile to Art Dimensionar Bloco para a Arte diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index b703c6206..ce5daa355 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -3105,6 +3105,7 @@ mark-style Japanese Японский Single Quotes: Одинарные кавычки: Single Right Quotation Mark Одинарная закрывающая кавычка Single-line Composer Однострочный компоновщик + Toggle Line Composer Переключить компоновщик строк Sixth Space Шестая шпация Size Размер Size Tile to Art Подогнать плитку по рисунку diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index 50f81c216..1ef7470b6 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -3003,6 +3003,7 @@ font-technology Variable Variabla Single Quotes: Enkla citattecken: Single Right Quotation Mark Enkelt höger citattecken Single-line Composer Enradssättare + Toggle Line Composer Växla radsättare Sixth Space Sjättedelsblanksteg Size Storlek Size Tile to Art Anpassa rutans storlek efter grafiken diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 24f375dd6..523f3bf3f 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -2914,6 +2914,7 @@ shape Open Açık Single Quotes: Tek Alıntılar: Single Right Quotation Mark Tek Sağ Tırnak İşareti Single-line Composer Tek Satır Oluşturucu + Toggle Line Composer Satır Oluşturucuyu Değiştir Sixth Space Altıncı Uzay Size Boyut Size Tile to Art Sanata Boyut Döşeme diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 4a43763d5..68b725bf2 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -3101,6 +3101,7 @@ mark-style Japanese Японський Single Quotes: Одинарні лапки: Single Right Quotation Mark Одинарна лапка, що закриває Single-line Composer Однорядковий компонувальник + Toggle Line Composer Переключити компонувальник рядків Sixth Space Шоста шпація Size Розмір Size Tile to Art Підігнати плитку за малюнком diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index 47e432bd5..7570055b2 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -3440,6 +3440,7 @@ mark-style Japanese Kiểu Nhật Single Quotes: Dấu nháy đơn: Single Right Quotation Mark Dấu nháy đơn đóng Single-line Composer Soạn thảo một dòng + Toggle Line Composer Chuyển đổi cách soạn dòng Sixth Space Dấu cách 1/6 Size Kích thước Size Tile to Art Kích thước ô theo đối tượng diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 7797a7e52..71a8fb202 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -2940,6 +2940,7 @@ font-script Japanese 汉字 Single Quotes: 单引号: Single Right Quotation Mark 右单引号 Single-line Composer 单行排版器 + Toggle Line Composer 切换行排版器 Sixth Space 六分之一空格 Size 大小 Size Tile to Art 使拼贴适合图稿 diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 907b56c30..13bf26f1a 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -3907,6 +3907,7 @@ font-script Japanese 漢字 Single Quotes: 單引號: Single Right Quotation Mark 右單引號 Single-line Composer 單行排版程式 + Toggle Line Composer 切換行排版程式 Sixth Space 六分之一空格 Size 大小 Size Tile to Art 拼貼符合圖稿大小 diff --git a/crates/ui-egui/src/menus/run.rs b/crates/ui-egui/src/menus/run.rs index ab1ab5a54..8dde979a7 100644 --- a/crates/ui-egui/src/menus/run.rs +++ b/crates/ui-egui/src/menus/run.rs @@ -239,6 +239,9 @@ fn run_ui_part3(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option crate::panels::character::highlight(app, crate::panels::character::Field::FontName), "type.highlightKerning" => crate::panels::character::highlight(app, crate::panels::character::Field::Kerning), "type.highlightTracking" => crate::panels::character::highlight(app, crate::panels::character::Field::Tracking), + "type.underline" => crate::panels::character::toggle_underline(app), + "type.lineComposer" => crate::panels::paragraph::toggle_composer(app), + "type.hyphenate" => crate::panels::paragraph::toggle_hyphenate(app), id if let Some((_, justify)) = crate::panels::paragraph::ALIGN_COMMANDS.iter().find(|c| c.0 == id) => { crate::panels::paragraph::align(app, justify) } diff --git a/crates/ui-egui/src/menus/state.rs b/crates/ui-egui/src/menus/state.rs index 8f2721f44..2d89d8b35 100644 --- a/crates/ui-egui/src/menus/state.rs +++ b/crates/ui-egui/src/menus/state.rs @@ -182,7 +182,9 @@ pub fn enabled(app: &VectorcraftApp, id: &str) -> bool { match id { // Save is off for a clean document that already has its own file. "file.save" => app.session.active().is_some_and(|d| d.path.is_none() || d.converted || d.is_dirty()), - "type.bold" | "type.italic" => crate::panels::character::text_style(app).is_some(), + "type.bold" | "type.italic" | "type.underline" | "type.lineComposer" | "type.hyphenate" => { + crate::panels::character::text_style(app).is_some() + } id if crate::panels::paragraph::ALIGN_COMMANDS.iter().any(|c| c.0 == id) => crate::panels::character::text_style(app).is_some(), "type.applyBullets" | "type.applyNumbers" | "type.convertListToText" => crate::panels::character::text_style(app).is_some(), id if let Some(b) = crate::panels::align::button(id) => enabled(app, b.command()), diff --git a/crates/ui-egui/src/menus/ui_commands.rs b/crates/ui-egui/src/menus/ui_commands.rs index 2104e5979..c87d53c2e 100644 --- a/crates/ui-egui/src/menus/ui_commands.rs +++ b/crates/ui-egui/src/menus/ui_commands.rs @@ -336,6 +336,24 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[ "", "{} show the Character panel if it is hidden and give its Tracking field the keyboard focus with its value selected: type a value and press Enter → {field: \"tracking\"}. Without selected type (or text the Type tool edits) the panel shows, and the error says to select type first", ), + ( + "type.underline", + "Underline", + "Cmd+Shift+U", + "{} the Character panel's Underline button: underline the selected type (or the Type tool's selection), or remove the underline when the text the Character panel shows is underlined (text.setFormat {underline}) → underlined", + ), + ( + "type.lineComposer", + "Toggle Line Composer", + "Cmd+Alt+Shift+C", + "{} the selected type's paragraphs (or those the Type tool's selection touches) use the Single-line Composer when they all use the Every-line Composer, else the Every-line Composer (text.setFormat {composer}) → \"singleLine\" | \"everyLine\"", + ), + ( + "type.hyphenate", + "Hyphenate", + "Cmd+Alt+Shift+H", + "{} the Paragraph panel's Hyphenate checkbox: hyphenation off for the selected type's paragraphs (or those the Type tool's selection touches) when they all hyphenate, else on (text.setFormat {hyphenate}) → hyphenate", + ), ("effect.last", "Last Effect…", "Cmd+Alt+Shift+E", "{} open the dialog of the last effect applied"), ("view.zoomIn", "Zoom In", "Cmd+=", "{}"), ("view.zoomOut", "Zoom Out", "Cmd+-", "{}"), diff --git a/crates/ui-egui/src/panels/character.rs b/crates/ui-egui/src/panels/character.rs index f788858f4..ff1c5a9c2 100644 --- a/crates/ui-egui/src/panels/character.rs +++ b/crates/ui-egui/src/panels/character.rs @@ -377,6 +377,14 @@ pub(crate) fn highlight(app: &mut VectorcraftApp, field: Field) -> Result Result { + let (s, _) = text_style(app).ok_or("select some type first")?; + format(app, json!({"underline": !s.underline})); + Ok(json!(!s.underline)) +} + /// `text.setRangeStyle` with `p` on the range the Type tool has selected (the whole text when /// nothing is selected). Does nothing unless the Type tool edits text. pub(crate) fn range_style(app: &mut VectorcraftApp, p: Value) { diff --git a/crates/ui-egui/src/panels/paragraph.rs b/crates/ui-egui/src/panels/paragraph.rs index 8662d512e..1952de032 100644 --- a/crates/ui-egui/src/panels/paragraph.rs +++ b/crates/ui-egui/src/panels/paragraph.rs @@ -50,6 +50,25 @@ pub(crate) fn align(app: &mut VectorcraftApp, justify: &str) -> Result Result { + text_style(app).ok_or("select some type first")?; + let id = if shared_composer(app) == Some(Composer::EveryLine) { "singleLine" } else { "everyLine" }; + format(app, json!({ "composer": id })); + Ok(json!(id)) +} + +/// `type.hyphenate` (Cmd+Alt+Shift+H): what the Hyphenate checkbox does, on the paragraphs the +/// panel acts on. Returns whether they now hyphenate. +pub(crate) fn toggle_hyphenate(app: &mut VectorcraftApp) -> Result { + text_style(app).ok_or("select some type first")?; + let on = shared_hyphenate(app) != Some(true); + format(app, json!({ "hyphenate": on })); + Ok(json!(on)) +} + fn para_cmd(app: &mut VectorcraftApp, cmd: &str, p: Value) { run_on_paragraphs(app, cmd, p).ok(); } diff --git a/crates/ui-egui/src/shortcuts/tests.rs b/crates/ui-egui/src/shortcuts/tests.rs index 3779daf64..8fa766f8c 100644 --- a/crates/ui-egui/src/shortcuts/tests.rs +++ b/crates/ui-egui/src/shortcuts/tests.rs @@ -384,6 +384,70 @@ fn cmd_shift_x_resets_horizontal_scale() { assert_eq!(scales(&mut app), [(json!("One "), json!(150.0)), (json!("Two"), json!(100.0))]); } +/// Cmd+Shift+U underlines the selected type and removes the underline again, Cmd+Alt+Shift+C +/// switches its paragraphs between the Single-line and the Every-line Composer, and +/// Cmd+Alt+Shift+H turns their hyphenation on and off. While the Type tool edits text, they act on +/// its selection and the paragraphs it touches. Smart Guides (Cmd+U), Copy (Cmd+C) and Hide +/// Artboards (Cmd+Shift+H) stay as they are. +#[test] +fn cmd_shift_u_and_cmd_alt_shift_c_and_h_toggle_type_formats() { + use vectorcraft_doc::Composer; + let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default()); + app.session.execute("file.new", &json!({"width": 200, "height": 200})).unwrap(); + let id = app.session.execute("text.create", &json!({"x": 20, "y": 50, "text": "One\nTwo"})).unwrap()["id"].as_u64().unwrap(); + let underlines = |app: &mut VectorcraftApp| { + let r = app.session.execute("text.getRange", &json!({"id": id})).unwrap(); + r["runs"].as_array().unwrap().iter().map(|run| (run["text"].clone(), run["style"]["underline"].clone())).collect::>() + }; + let paras = |app: &VectorcraftApp| match &app.session.active().unwrap().doc.node(vectorcraft_doc::NodeId(id)).unwrap().kind { + vectorcraft_doc::NodeKind::Text(t) => (0..t.paragraph_count()).map(|i| (t.para_at(i).composer, t.para_at(i).hyphenate)).collect::>(), + _ => panic!("text"), + }; + let chord = + |key, m: Modifiers| vec![egui::Event::Key { key, physical_key: None, pressed: true, repeat: false, modifiers: Modifiers::COMMAND | m }]; + let (shift, alt_shift) = (Modifiers::SHIFT, Modifiers::ALT | Modifiers::SHIFT); + let (guides, artboards) = (app.ui.view.smart_guides, app.ui.view.artboards); + assert!(app.session.clipboard.is_empty()); + app.session.execute("select.set", &json!({"ids": [id]})).unwrap(); + let hyphenate = paras(&app)[0].1; + frame(&mut app, chord(Key::U, shift)); + assert_eq!(underlines(&mut app), [(json!("One\nTwo"), json!(true))]); + frame(&mut app, chord(Key::U, shift)); + assert_eq!(underlines(&mut app), [(json!("One\nTwo"), json!(false))]); + frame(&mut app, chord(Key::C, alt_shift)); + assert_eq!(paras(&app), [(Composer::SingleLine, hyphenate); 2]); + frame(&mut app, chord(Key::C, alt_shift)); + assert_eq!(paras(&app), [(Composer::EveryLine, hyphenate); 2]); + frame(&mut app, chord(Key::H, alt_shift)); + assert_eq!(paras(&app), [(Composer::EveryLine, !hyphenate); 2]); + frame(&mut app, chord(Key::H, alt_shift)); + assert_eq!(paras(&app), [(Composer::EveryLine, hyphenate); 2]); + assert_eq!((app.ui.view.smart_guides, app.ui.view.artboards, app.session.clipboard.is_empty()), (guides, artboards, true)); + // While the Type tool edits: its selected text, and the paragraph that text is in. + 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": 4, "end": 7})); + assert!(app.session.tool_wants_text()); + for (key, m) in [(Key::U, shift), (Key::C, alt_shift), (Key::H, alt_shift)] { + frame(&mut app, chord(key, m)); + } + assert_eq!(underlines(&mut app), [(json!("One\n"), json!(false)), (json!("Two"), json!(true))]); + assert_eq!(paras(&app), [(Composer::EveryLine, hyphenate), (Composer::SingleLine, !hyphenate)]); + // Paragraphs with different composers and hyphenation take the Every-line Composer and + // hyphenation, as the Hyphenate checkbox turns it on for them. + app.select_tool("selection"); + app.session.execute("select.set", &json!({"ids": [id]})).unwrap(); + for (key, m) in [(Key::C, alt_shift), (Key::H, alt_shift)] { + frame(&mut app, chord(key, m)); + } + assert_eq!(paras(&app), [(Composer::EveryLine, true); 2]); + // Nothing selected: nothing to change. + app.session.execute("select.none", &json!({})).unwrap(); + for id in ["type.underline", "type.lineComposer", "type.hyphenate"] { + assert!(!crate::menus::enabled(&app, id), "{id}"); + } +} + /// Tab shows and hides the panels, and in the Type tool it types a tab, without moving the /// keyboard focus on to a field: the keys after it (a tool letter, the next letter typed) still /// work. diff --git a/docs/mcp.md b/docs/mcp.md index 315e60393..4ffc83593 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -3100,6 +3100,10 @@ Pen's second anchor at (150, 431), in line with the square's centre. give its Kerning or Tracking field the keyboard focus with the value selected, or open its font family menu with the search field focused; each replies `{field: "kerning" | "tracking" | "fontName"}`. Without selected type or text the Type tool edits, the panel shows and the command fails. + shows it, in the same text; at a caret it leaves the text as it is. The UI command `type.underline` (Cmd+Shift+U, + in remote mode `press_key {key: "U", mods: {cmd: true, shift: true}}` or `invoke_menu`) does what the Character + panel's Underline button does: it underlines the Type tool's selected text or the selected type objects, or removes + the underline when the text the panel shows is underlined, and returns whether the text is now underlined. - `missingGlyphProtection` (on by default): `text.setStyle` and `text.setRangeStyle` changing the font leave the characters the new font has no glyph for in the font that had one. - `typeSelectionByPathOnly` (off by default): on, the Selection tools (`pointer_gesture` with `selection`, and the @@ -4542,7 +4546,10 @@ The letter and line counts are rounded, and every value is clamped to its range. listed word. The options are saved with the paragraph (`hyphenation` in `para`) only when they differ from the defaults, and paragraph styles carry them (`paraStyle.new {attrs: {hyphenation: {words_longer_than: 8}}}`). One undo step. `ui.hyphenation` opens the Hyphenation dialog on the values the Paragraph panel shows; OK sends the values that -changed. +changed. The UI command `type.hyphenate` (Cmd+Alt+Shift+H, in remote mode `press_key {key: "H", mods: {cmd: true, +alt: true, shift: true}}` or `invoke_menu`) does what the Hyphenate checkbox does: it turns `hyphenate` off when +every paragraph of the selected type (or every paragraph the Type tool's selection touches) hyphenates, else on, and +returns the new value. ```json {"name":"run_command","arguments":{"command":"text.setFormat","params":{"hyphenate":true,"wordsLongerThan":8,"hyphenLimit":2}}} @@ -5493,6 +5500,9 @@ Single-line fills each line as far as it goes. Point type and type on a path hav give the same result there. A paragraph whose characters differ in line metrics (type size, font, leading or vertical scale, or an inline graphic taller than the text) is composed with Every-line in rectangular area type, rows and columns included; in area type of another shape, or with text wrap, it falls back to Single-line. +The UI command `type.lineComposer` (Cmd+Alt+Shift+C, in remote mode `press_key {key: "C", mods: {cmd: true, alt: true, +shift: true}}` or `invoke_menu`) sets `singleLine` when every paragraph of the selected type (or every paragraph the +Type tool's selection touches) uses Every-line, else `everyLine`, and returns the composer it set. ```json {"name":"run_command","arguments":{"command":"text.setFormat","params":{"ids":[7],"composer":"singleLine"}}} diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 73f40f91f..84a46130b 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -622,6 +622,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - Cmd/Ctrl+Alt+L (`ui.newLayer`) opens Layer Options for a new layer, as an Alt-click on the Layers panel's New Layer button does, on the key the reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists for adding a layer through the New Layer dialog box. OK adds the layer above the current layer, and Cancel adds none. Cmd/Ctrl+L still adds a layer without the dialog. - F8 (`ui.symbolOptions`) opens Symbol Options for a new symbol made from the selection, as the Symbols panel's New Symbol button does, on the key the reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists for making a new symbol. OK makes the symbol and puts an instance of it in place of the art, and Cancel makes none. With nothing selected, F8 opens no dialog, and the status bar says that nothing is selected. Shift+F8 and Cmd/Ctrl+F8 still show the Transform and Info panels. - Cmd/Ctrl+Shift+X (`type.resetHorizontalScale`) sets the horizontal scale of the selected type, or of the text the Type tool has selected, to 100% as the Character panel shows it (the object's own stretch included), in one undo step; at a caret it leaves the text as it is. + - Cmd/Ctrl+Shift+U (`type.underline`) underlines the selected type, or the text the Type tool has selected, and removes the underline again, as the Character panel's Underline button does. Cmd/Ctrl+Alt+Shift+C (`type.lineComposer`) switches the paragraphs between the Single-line and the Every-line Composer, and Cmd/Ctrl+Alt+Shift+H (`type.hyphenate`) turns their hyphenation on and off, as the Hyphenate checkbox does. These are the keys the reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists for underlining and for toggling auto-hyphenation, and on Windows for toggling the line composer. The page's macOS key for the line composer ends after Command, and VectorCraft uses C there as well. - Cmd/Ctrl+Alt+N (`file.newWithoutDialog`) makes a document without opening the New Document dialog, on the key the reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists for making a new document with no New Document dialog box. The page does not say which settings the document gets. VectorCraft gives it the settings the dialog opens on (the first Recent entry, or the Print category's Letter while Recent is empty) and the next untitled name. - Cmd/Ctrl+F6 (`window.nextDocument`) and Cmd/Ctrl+Shift+F6 (`window.previousDocument`) make the next and the previous open document the current one, in tab order and as a click on its tab does, on the keys the reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists for navigating to the next and the previous document. After the last document comes the first, and before the first document comes the last. From the Home screen the keys go to the first and the last document. Keyboard Shortcuts lists both under Window. - Cmd/Ctrl+Alt+Shift+U (`document.switchUnits`) switches the document to the next unit of measurement, in one undo step, on the key the reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) page lists for switching units of measurement. The page does not give an order. VectorCraft steps through the units in the order a right-click on a ruler lists them (Points, Picas, Inches, Millimeters, Centimeters, Pixels, Feet & Inches, Meters, Yards, Feet) and goes from Feet back to Points.