mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-11 02:19:56 -06:00
Keyboard Shortcuts: Export Text saves the shortcut list as a text file
Edit > Keyboard Shortcuts gains Export Text..., which saves the set shown
in the dialog, as edited so far, as a UTF-8 text file the user names in a
save dialog with a .txt filter. shortcuts.exportText {path?} does the same
for the current set over MCP and the control channel.
The file holds a "Keyboard Shortcuts" line and the set's name, then a
Tools and a Menu Commands section with the rows the dialog lists, in its
order and named as it shows them: the name, a tab and the shortcuts as the
dialog shows them on the current platform. A row with no shortcut ends
after the tab. A path that is not a string, or a file that cannot be
written, returns an error and nothing is written.
Docs: docs/mcp.md, docs/target-app-parity.md.
This commit is contained in:
@@ -1060,6 +1060,8 @@ font-technology Variable Променливи
|
||||
Export for Screens Settings Настройки за експортиране за екрани
|
||||
Export for Screens… Експортиране за екрани…
|
||||
Export Keyboard Shortcuts… Експортиране на клавишни комбинации…
|
||||
Export Keyboard Shortcuts as Text… Експортиране на клавишни комбинации като текст…
|
||||
Export Text… Експортиране на текст…
|
||||
Export Option Опция за експортиране
|
||||
Export PDF Експортиране в PDF
|
||||
Export PDF Presets Предварителни настройки за PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -938,6 +938,8 @@ lighting Light Svjetlo
|
||||
Expand Layers Panel Rows Proširi redove panela slojeva
|
||||
Export CSS… Izvezi CSS…
|
||||
Export Keyboard Shortcuts… Izvezi prečice na tastaturi…
|
||||
Export Keyboard Shortcuts as Text… Izvezi prečice na tastaturi kao tekst…
|
||||
Export Text… Izvezi tekst…
|
||||
File Info Dialog Dijalog informacija o datoteci
|
||||
Go to Artboard Idi na radnu ploču
|
||||
First Artboard Prva radna ploča
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1466,6 +1466,8 @@
|
||||
Export for Screens Settings Configuració d’exportació per a pantalles
|
||||
Export for Screens… Exporta per a pantalles…
|
||||
Export Keyboard Shortcuts… Exporta les dreceres de teclat…
|
||||
Export Keyboard Shortcuts as Text… Exporta les dreceres de teclat com a text…
|
||||
Export Text… Exporta el text…
|
||||
Export Layer Exporta la capa
|
||||
Export Library Exporta la biblioteca
|
||||
Export Library… Exporta la biblioteca…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -957,6 +957,8 @@ lighting Light Světlo
|
||||
Expand Layers Panel Rows Rozbalit řádky panelu Vrstvy
|
||||
Export CSS… Exportovat CSS…
|
||||
Export Keyboard Shortcuts… Exportovat klávesové zkratky…
|
||||
Export Keyboard Shortcuts as Text… Exportovat klávesové zkratky jako text…
|
||||
Export Text… Exportovat text…
|
||||
File Info Dialog Dialogové okno Informace o souboru
|
||||
Go to Artboard Přejít na pracovní plochu
|
||||
First Artboard První pracovní plocha
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -878,6 +878,8 @@ lighting Light Lys
|
||||
Expand Layers Panel Rows Udvid rækker i lagpanelet
|
||||
Export CSS… Eksportér CSS…
|
||||
Export Keyboard Shortcuts… Eksportér tastaturgenveje…
|
||||
Export Keyboard Shortcuts as Text… Eksportér tastaturgenveje som tekst…
|
||||
Export Text… Eksportér tekst…
|
||||
File Info Dialog Dialogboks til filoplysninger
|
||||
Go to Artboard Gå til tegnebræt
|
||||
Graphic Style Options… Indstillinger for grafisk typografi…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1060,6 +1060,8 @@ font-technology Variable Variabel
|
||||
Export for Screens Settings Einstellungen für „Für Bildschirme exportieren“
|
||||
Export for Screens… Für Bildschirme exportieren…
|
||||
Export Keyboard Shortcuts… Tastaturbefehle exportieren…
|
||||
Export Keyboard Shortcuts as Text… Tastaturbefehle als Text exportieren…
|
||||
Export Text… Text exportieren…
|
||||
Export Option Exportoption
|
||||
Export PDF PDF exportieren
|
||||
Export PDF Presets PDF-Vorgaben exportieren
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1033,6 +1033,8 @@ font-technology Variable Μεταβλητές
|
||||
Export for Screens Settings Ρυθμίσεις εξαγωγής για οθόνες
|
||||
Export for Screens… Εξαγωγή για οθόνες…
|
||||
Export Keyboard Shortcuts… Εξαγωγή συντομεύσεων πληκτρολογίου…
|
||||
Export Keyboard Shortcuts as Text… Εξαγωγή συντομεύσεων πληκτρολογίου ως κείμενο…
|
||||
Export Text… Εξαγωγή κειμένου…
|
||||
Export Option Επιλογή εξαγωγής
|
||||
Export PDF Εξαγωγή PDF
|
||||
Export PDF Presets Εξαγωγή προεπιλογών PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 163 and column 5.
|
@@ -1089,6 +1089,8 @@ font-technology Variable Variables
|
||||
Export for Screens Settings Ajustes de Exportar para pantallas
|
||||
Export for Screens… Exportar para pantallas…
|
||||
Export Keyboard Shortcuts… Exportar métodos abreviados de teclado…
|
||||
Export Keyboard Shortcuts as Text… Exportar métodos abreviados de teclado como texto…
|
||||
Export Text… Exportar texto…
|
||||
Export Option Opción de exportación
|
||||
Export PDF Exportar PDF
|
||||
Export PDF Presets Exportar preajustes de PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -936,6 +936,8 @@ lighting Light Valo
|
||||
Expand Layers Panel Rows Laajenna tasopaneelin rivit
|
||||
Export CSS… Vie CSS…
|
||||
Export Keyboard Shortcuts… Vie pikanäppäimet…
|
||||
Export Keyboard Shortcuts as Text… Vie pikanäppäimet tekstinä…
|
||||
Export Text… Vie teksti…
|
||||
File Info Dialog Tiedoston tiedot -valintaikkuna
|
||||
Go to Artboard Siirry piirtoalustaan
|
||||
First Artboard Ensimmäinen piirtoalusta
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1084,6 +1084,8 @@ font-technology Variable Variables
|
||||
Export for Screens Settings Paramètres d’Exporter pour les écrans
|
||||
Export for Screens… Exporter pour les écrans…
|
||||
Export Keyboard Shortcuts… Exporter les raccourcis clavier…
|
||||
Export Keyboard Shortcuts as Text… Exporter les raccourcis clavier en texte…
|
||||
Export Text… Exporter le texte…
|
||||
Export Option Option d’exportation
|
||||
Export PDF Exporter en PDF
|
||||
Export PDF Presets Exporter les paramètres prédéfinis PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1631,6 +1631,8 @@
|
||||
Export for Screens Settings स्क्रीन सेटिंग के लिए निर्यात
|
||||
Export for Screens… स्क्रीन के लिए निर्यात…
|
||||
Export Keyboard Shortcuts… कीबोर्ड शॉर्टकट निर्यात करें…
|
||||
Export Keyboard Shortcuts as Text… कीबोर्ड शॉर्टकट टेक्स्ट के रूप में निर्यात करें…
|
||||
Export Text… टेक्स्ट निर्यात करें…
|
||||
Export Layer निर्यात लेयर
|
||||
Export Library लाइब्रेरी
|
||||
Export Library… लाइब्रेरी निर्यात करें…
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -1367,6 +1367,8 @@ font-technology Variable Változó
|
||||
Export for Screens Settings Exportálás képernyőkre – beállítások
|
||||
Export for Screens… Exportálás képernyőkre…
|
||||
Export Keyboard Shortcuts… Billentyűparancsok exportálása…
|
||||
Export Keyboard Shortcuts as Text… Billentyűparancsok exportálása szövegként…
|
||||
Export Text… Szöveg exportálása…
|
||||
Export Library Könyvtár exportálása
|
||||
Export Library… Könyvtár exportálása…
|
||||
Export Option Exportálási beállítás
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -878,6 +878,8 @@ lighting Light Cahaya
|
||||
Expand Layers Panel Rows Perluas baris panel Lapisan
|
||||
Export CSS… Ekspor CSS…
|
||||
Export Keyboard Shortcuts… Ekspor pintasan papan ketik…
|
||||
Export Keyboard Shortcuts as Text… Ekspor pintasan papan ketik sebagai teks…
|
||||
Export Text… Ekspor teks…
|
||||
File Info Dialog Dialog info file
|
||||
Go to Artboard Buka artboard
|
||||
Graphic Style Options… Opsi gaya grafis…
|
||||
|
||||
|
@@ -1090,6 +1090,8 @@ font-technology Variable Variabili
|
||||
Export for Screens Settings Impostazioni Esporta per schermi
|
||||
Export for Screens… Esporta per schermi…
|
||||
Export Keyboard Shortcuts… Esporta scelte rapide da tastiera…
|
||||
Export Keyboard Shortcuts as Text… Esporta scelte rapide da tastiera come testo…
|
||||
Export Text… Esporta testo…
|
||||
Export Option Opzione di esportazione
|
||||
Export PDF Esporta PDF
|
||||
Export PDF Presets Esporta preset PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1581,6 +1581,8 @@ digits Malayalam マラヤーラム数字
|
||||
Export Document ドキュメントを書き出し
|
||||
Export EPS EPS を書き出し
|
||||
Export Keyboard Shortcuts… キーボードショートカットを書き出し…
|
||||
Export Keyboard Shortcuts as Text… キーボードショートカットをテキストで書き出し…
|
||||
Export Text… テキストを書き出し…
|
||||
Export Option 書き出しオプション
|
||||
Export PDF PDF を書き出し
|
||||
Export PDF Presets PDF プリセットを書き出し
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -831,6 +831,8 @@ lighting Light სინათლე
|
||||
Expand Layers Panel Rows შრეების პანელის სტრიქონების გაშლა
|
||||
Export CSS… CSS-ის ექსპორტირება…
|
||||
Export Keyboard Shortcuts… კლავიატურის მალსახმობების ექსპორტირება…
|
||||
Export Keyboard Shortcuts as Text… კლავიატურის მალსახმობების ტექსტად ექსპორტირება…
|
||||
Export Text… ტექსტის ექსპორტი…
|
||||
File Info Dialog ფაილის ინფორმაციის დიალოგი
|
||||
Go to Artboard სამუშაო დაფაზე გადასვლა
|
||||
Graphic Style Options… გრაფიკული სტილის პარამეტრები…
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -1571,6 +1571,8 @@ digits Malayalam 말라얄람어
|
||||
Export Document 문서 내보내기
|
||||
Export EPS EPS 내보내기
|
||||
Export Keyboard Shortcuts… 단축키 내보내기…
|
||||
Export Keyboard Shortcuts as Text… 단축키를 텍스트로 내보내기…
|
||||
Export Text… 텍스트 내보내기…
|
||||
Export Option 내보내기 옵션
|
||||
Export PDF PDF 내보내기
|
||||
Export PDF Presets PDF 프리셋 내보내기
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -892,6 +892,8 @@ lighting Light Licht
|
||||
Expand Layers Panel Rows Rijen in het Lagen-paneel uitvouwen
|
||||
Export CSS… CSS exporteren…
|
||||
Export Keyboard Shortcuts… Sneltoetsen exporteren…
|
||||
Export Keyboard Shortcuts as Text… Sneltoetsen als tekst exporteren…
|
||||
Export Text… Tekst exporteren…
|
||||
File Info Dialog Dialoogvenster bestandsinfo
|
||||
Go to Artboard Ga naar tekengebied
|
||||
Graphic Style Options… Opties voor grafische stijl…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -894,6 +894,8 @@ lighting Light Światło
|
||||
Expand Layers Panel Rows Rozwiń wiersze panelu Warstwy
|
||||
Export CSS… Eksportuj CSS…
|
||||
Export Keyboard Shortcuts… Eksportuj skróty klawiaturowe…
|
||||
Export Keyboard Shortcuts as Text… Eksportuj skróty klawiaturowe jako tekst…
|
||||
Export Text… Eksportuj tekst…
|
||||
File Info Dialog Okno informacji o pliku
|
||||
Go to Artboard Przejdź do obszaru kompozycji
|
||||
First Artboard Pierwszy obszar kompozycji
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -981,6 +981,8 @@
|
||||
Export Document Exportar Documento
|
||||
Export EPS Exportar EPS
|
||||
Export Keyboard Shortcuts… Exportar Atalhos de Teclado…
|
||||
Export Keyboard Shortcuts as Text… Exportar Atalhos de Teclado como Texto…
|
||||
Export Text… Exportar Texto…
|
||||
Export Option Opção de Exportação
|
||||
Export PDF Exportar PDF
|
||||
Export PDF Presets Exportar Predefinidos de PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -1087,6 +1087,8 @@ font-technology Variable Вариативные
|
||||
Export for Screens Settings Параметры экспорта для экранов
|
||||
Export for Screens… Экспортировать для экранов…
|
||||
Export Keyboard Shortcuts… Экспортировать сочетания клавиш…
|
||||
Export Keyboard Shortcuts as Text… Экспортировать сочетания клавиш как текст…
|
||||
Export Text… Экспорт текста…
|
||||
Export Option Параметр экспорта
|
||||
Export PDF Экспортировать PDF
|
||||
Export PDF Presets Экспортировать наборы PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1068,6 +1068,8 @@ font-technology Variable Variabla
|
||||
Export for Screens Settings Inställningar för Exportera för skärmar
|
||||
Export for Screens… Exportera för skärmar…
|
||||
Export Keyboard Shortcuts… Exportera kortkommandon…
|
||||
Export Keyboard Shortcuts as Text… Exportera kortkommandon som text…
|
||||
Export Text… Exportera text…
|
||||
Export Option Exportalternativ
|
||||
Export PDF Exportera PDF
|
||||
Export PDF Presets Exportera PDF-förinställningar
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -1060,6 +1060,8 @@ font-technology Variable Değişken
|
||||
Export for Screens Settings Ekran Ayarları için Dışa Aktarma
|
||||
Export for Screens… Ekranlar için Dışa Aktarma…
|
||||
Export Keyboard Shortcuts… Klavye Kısayollarını Dışa Aktar…
|
||||
Export Keyboard Shortcuts as Text… Klavye Kısayollarını Metin Olarak Dışa Aktar…
|
||||
Export Text… Metni Dışa Aktar…
|
||||
Export Option Dışa Aktarma Seçeneği
|
||||
Export PDF PDF'yi dışa aktar
|
||||
Export PDF Presets PDF Hazır Ayarlarını Dışa Aktar
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -1084,6 +1084,8 @@ font-technology Variable Варіативні
|
||||
Export for Screens Settings Параметри експорту для екранів
|
||||
Export for Screens… Експортувати для екранів…
|
||||
Export Keyboard Shortcuts… Експортувати сполучення клавіш…
|
||||
Export Keyboard Shortcuts as Text… Експортувати сполучення клавіш як текст…
|
||||
Export Text… Експорт тексту…
|
||||
Export Option Параметр експорту
|
||||
Export PDF Експортувати PDF
|
||||
Export PDF Presets Експортувати набори PDF
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 177 and column 5.
|
@@ -1244,6 +1244,8 @@ font-technology Variable Biến thiên
|
||||
Export for Screens Settings Cài đặt xuất cho màn hình
|
||||
Export for Screens… Xuất cho màn hình…
|
||||
Export Keyboard Shortcuts… Xuất phím tắt…
|
||||
Export Keyboard Shortcuts as Text… Xuất phím tắt dưới dạng văn bản…
|
||||
Export Text… Xuất văn bản…
|
||||
Export Library Xuất thư viện
|
||||
Export Library… Xuất thư viện…
|
||||
Export Option Tùy chọn xuất
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 199 and column 5.
|
@@ -1030,6 +1030,8 @@
|
||||
Export for Screens Settings 导出为屏幕所用格式设置
|
||||
Export for Screens… 导出为屏幕所用格式…
|
||||
Export Keyboard Shortcuts… 导出键盘快捷键…
|
||||
Export Keyboard Shortcuts as Text… 将键盘快捷键导出为文本…
|
||||
Export Text… 导出文本…
|
||||
Export Option 导出选项
|
||||
Export PDF 导出 PDF
|
||||
Export PDF Presets 导出 PDF 预设
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1054,6 +1054,8 @@ font-technology Variable 可變
|
||||
Export for Screens Settings 匯出為螢幕適用設定
|
||||
Export for Screens… 匯出為螢幕適用…
|
||||
Export Keyboard Shortcuts… 匯出鍵盤快速鍵…
|
||||
Export Keyboard Shortcuts as Text… 將鍵盤快速鍵匯出為文字…
|
||||
Export Text… 匯出文字…
|
||||
Export Option 匯出選項
|
||||
Export PDF 匯出 PDF
|
||||
Export PDF Presets 匯出 PDF 預設集
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -167,6 +167,12 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
|
||||
"{name: \"VectorCraft Defaults\" | \"Classic Defaults\"} (names of earlier versions are accepted)",
|
||||
),
|
||||
("shortcuts.export", "Export Keyboard Shortcuts…", "", "{path?}"),
|
||||
(
|
||||
"shortcuts.exportText",
|
||||
"Export Keyboard Shortcuts as Text…",
|
||||
"",
|
||||
"{path?} save the current set's tools and menu commands with their shortcuts as a UTF-8 text file (Keyboard Shortcuts › Export Text…): the set's name, then a Tools and a Menu Commands section in the dialog's order, one `name<TAB>shortcut` line per row, empty after the tab when it has none; without `path`, pick a file",
|
||||
),
|
||||
("shortcuts.import", "Import Keyboard Shortcuts…", "", "{path? | data?}"),
|
||||
(
|
||||
"ui.shortcutImportDialog",
|
||||
|
||||
@@ -76,6 +76,7 @@ const DOCUMENT_FREE: &[&str] = &[
|
||||
"ui.libraryPanel.locate",
|
||||
"shortcuts.import",
|
||||
"shortcuts.export",
|
||||
"shortcuts.exportText",
|
||||
"ui.shortcutImportDialog",
|
||||
crate::panels::actions::SAVE_SET,
|
||||
crate::panels::actions::LOAD_SET,
|
||||
|
||||
@@ -700,6 +700,25 @@ pub fn import_json(v: &Value) -> Result<(String, Overrides), String> {
|
||||
Ok((v.get("set").and_then(Value::as_str).map_or(CUSTOM, set_name).to_string(), out))
|
||||
}
|
||||
|
||||
/// Export Text: the set's name, then the dialog's Tools and Menu Commands lists in its order, one
|
||||
/// row per line with the name and the shortcuts as the dialog shows them, separated by a tab. A
|
||||
/// row with no shortcut ends after the tab.
|
||||
pub fn export_text(set: &str, overrides: &Overrides) -> String {
|
||||
let km = keymap_with(overrides);
|
||||
let backtick = backtick_text();
|
||||
let shown_set = if PRESETS.contains(&set) || set == CUSTOM { tl!(set) } else { set };
|
||||
let mut out = format!("{}\n{} {shown_set}\n", tl!("Keyboard Shortcuts"), tl!("Set:"));
|
||||
for (tools, heading) in [(true, "Tools"), (false, "Menu Commands")] {
|
||||
out += &format!("\n{}\n", tl!(heading));
|
||||
for e in entries().iter().filter(|e| e.is_tool == tools && listed(km.overrides(), e)) {
|
||||
let name = if e.is_tool || e.group.is_empty() { tl!(&e.label).to_string() } else { format!("{} › {}", tl!(&e.group), tl!(&e.label)) };
|
||||
let sc = dialog_shortcuts_with(&km, &e.key, backtick.as_deref()).unwrap_or_default();
|
||||
out += &format!("{name}\t{sc}\n");
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
// ---------- UI commands ----------
|
||||
|
||||
pub fn open(app: &mut VectorcraftApp) {
|
||||
@@ -800,6 +819,31 @@ pub fn run_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<Resu
|
||||
},
|
||||
}
|
||||
}
|
||||
"shortcuts.exportText" => {
|
||||
let path = match p.get("path") {
|
||||
None | Some(Value::Null) => None,
|
||||
Some(Value::String(path)) => Some(path.clone()),
|
||||
Some(_) => {
|
||||
let key = "path";
|
||||
return Some(Err(format!("`{key}` must be a string")));
|
||||
}
|
||||
};
|
||||
let text = export_text(&app.ui.shortcut_set, &app.ui.shortcut_overrides);
|
||||
let pick =
|
||||
crate::FilePick { filters: vec![crate::FilePick::filter("Text", &["txt"])], ..crate::FilePick::named("VectorCraft Shortcuts.txt") };
|
||||
match path.or_else(|| crate::picks::save(app, &pick)) {
|
||||
Some(path) => match app.services.write.as_mut() {
|
||||
Some(w) => w(&path, text.as_bytes()).map(|_| json!({"path": path})),
|
||||
None => Err("no file writer".into()),
|
||||
},
|
||||
// Its save dialog is open: the file is written when it answers.
|
||||
None if app.file_dialog_open() => Err("cancelled".into()),
|
||||
None => match app.services.download.as_mut() {
|
||||
Some(dl) => dl("VectorCraft Shortcuts.txt", text.as_bytes()).map(|()| Value::Null),
|
||||
None => Ok(json!({"text": text})),
|
||||
},
|
||||
}
|
||||
}
|
||||
"shortcuts.import" => {
|
||||
let data = if let Some(v) = p.get("data") {
|
||||
Ok(v.clone())
|
||||
@@ -947,6 +991,9 @@ pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
if ui.button(tl!("Export…")).clicked() {
|
||||
d.fields.insert("__export".into(), json!(true));
|
||||
}
|
||||
if ui.button(tl!("Export Text…")).clicked() {
|
||||
d.fields.insert("__exportText".into(), json!(true));
|
||||
}
|
||||
if ui.button(tl!("Reset to Defaults")).clicked() {
|
||||
km.to_mut().reset_all();
|
||||
d.fields.insert("set".into(), json!(PRESETS[0]));
|
||||
@@ -1090,6 +1137,7 @@ pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
}
|
||||
let import = d.fields.remove("__import").is_some();
|
||||
let export = d.fields.remove("__export").is_some();
|
||||
let export_text = d.fields.remove("__exportText").is_some();
|
||||
app.ui.dialog = Some(d);
|
||||
// Their file dialogs, shown off the UI thread, import into or export from the dialog as it is
|
||||
// when they answer.
|
||||
@@ -1099,6 +1147,9 @@ pub fn show(app: &mut VectorcraftApp, ctx: &egui::Context) {
|
||||
if export {
|
||||
crate::picks::button(app, export_from_dialog);
|
||||
}
|
||||
if export_text {
|
||||
crate::picks::button(app, export_text_from_dialog);
|
||||
}
|
||||
if cancel {
|
||||
app.ui.dialog = None;
|
||||
} else if ok && let Err(e) = confirm(app) {
|
||||
@@ -1137,6 +1188,16 @@ fn import_into_dialog(app: &mut VectorcraftApp) {
|
||||
|
||||
/// The dialog's Export…: its working set, as edited so far.
|
||||
fn export_from_dialog(app: &mut VectorcraftApp) {
|
||||
export_dialog_set(app, "shortcuts.export");
|
||||
}
|
||||
|
||||
/// The dialog's Export Text…: its working set, as edited so far, as a text file.
|
||||
fn export_text_from_dialog(app: &mut VectorcraftApp) {
|
||||
export_dialog_set(app, "shortcuts.exportText");
|
||||
}
|
||||
|
||||
/// Runs `command` on the dialog's working set and set name.
|
||||
fn export_dialog_set(app: &mut VectorcraftApp, command: &str) {
|
||||
if !shortcuts_dialog(app) {
|
||||
app.status(crate::picks::dialog_gone());
|
||||
return;
|
||||
@@ -1144,7 +1205,7 @@ fn export_from_dialog(app: &mut VectorcraftApp) {
|
||||
let (ov, set) = app.ui.dialog.as_ref().map(|d| (dialog_overrides(d), d.str("set"))).unwrap_or_default();
|
||||
let saved = std::mem::replace(&mut app.ui.shortcut_overrides, ov);
|
||||
let saved_set = std::mem::replace(&mut app.ui.shortcut_set, set);
|
||||
if let Some(Err(e)) = run_command(app, "shortcuts.export", &json!({})) {
|
||||
if let Some(Err(e)) = run_command(app, command, &json!({})) {
|
||||
app.status(e);
|
||||
}
|
||||
app.ui.shortcut_overrides = saved;
|
||||
@@ -1453,6 +1514,82 @@ mod tests {
|
||||
assert!(import_json(&json!({})).is_err());
|
||||
}
|
||||
|
||||
/// An Export Text line: the row's name as the dialog shows it, a tab and `shortcut`.
|
||||
fn text_row(key: &str, shortcut: &str) -> String {
|
||||
let e = entry(key).unwrap_or_else(|| panic!("no entry {key}"));
|
||||
if e.is_tool || e.group.is_empty() { format!("{}\t{shortcut}", e.label) } else { format!("{} › {}\t{shortcut}", e.group, e.label) }
|
||||
}
|
||||
|
||||
/// Export Text writes the set's name, then the Tools and the Menu Commands rows in the dialog's
|
||||
/// order, each with its shortcut as the dialog shows it.
|
||||
#[test]
|
||||
fn export_text_lists_the_dialogs_rows_with_their_shortcuts() {
|
||||
let mut ov = Overrides::new();
|
||||
crate::keymap::set_override(&mut ov, "edit.preferences", "Ctrl+Alt+Shift+9");
|
||||
let text = export_text("VectorCraft Defaults", &ov);
|
||||
let lines: Vec<&str> = text.lines().collect();
|
||||
assert_eq!(lines[..4], ["Keyboard Shortcuts", "Set: VectorCraft Defaults", "", "Tools"]);
|
||||
let menu_at = lines.iter().position(|l| *l == "Menu Commands").expect("a Menu Commands section");
|
||||
assert_eq!(lines[menu_at - 1], "", "a blank line before Menu Commands");
|
||||
let km = keymap_with(&ov);
|
||||
let names = |tools: bool| -> Vec<String> {
|
||||
entries().iter().filter(|e| e.is_tool == tools && listed(km.overrides(), e)).map(|e| text_row(&e.key, "")).collect()
|
||||
};
|
||||
let names_of = |rows: &[&str]| -> Vec<String> { rows.iter().map(|l| format!("{}\t", l.split('\t').next().unwrap_or_default())).collect() };
|
||||
assert_eq!(names_of(&lines[4..menu_at - 1]), names(true), "the Tools rows, in the dialog's order");
|
||||
assert_eq!(names_of(&lines[menu_at + 1..]), names(false), "the Menu Commands rows, in the dialog's order");
|
||||
let pen = menus::pretty_shortcut(default_of("tool:pen").expect("the Pen tool has a default key"));
|
||||
assert!(lines[4..menu_at].contains(&text_row("tool:pen", &pen).as_str()), "{text}");
|
||||
let prefs = menus::pretty_shortcut(&effective_with(&km, "edit.preferences").expect("the shortcut set"));
|
||||
assert!(prefs.ends_with('9'), "{prefs}");
|
||||
assert!(lines[menu_at..].contains(&text_row("edit.preferences", &prefs).as_str()), "{text}");
|
||||
assert!(text.ends_with('\n'));
|
||||
}
|
||||
|
||||
/// A command without a shortcut is listed with nothing after the tab: one without a default key
|
||||
/// and one whose shortcut the set clears.
|
||||
#[test]
|
||||
fn export_text_lists_a_command_without_a_shortcut_with_an_empty_shortcut() {
|
||||
let mut ov = Overrides::new();
|
||||
crate::keymap::set_override(&mut ov, "edit.preferences", "");
|
||||
assert!(default_of("align.horizontalLeft").is_none());
|
||||
let text = export_text(CUSTOM, &ov);
|
||||
let lines: Vec<&str> = text.lines().collect();
|
||||
assert_eq!(lines[1], "Set: Custom");
|
||||
for key in ["align.horizontalLeft", "edit.preferences"] {
|
||||
assert!(lines.contains(&text_row(key, "").as_str()), "{key}: {text}");
|
||||
}
|
||||
}
|
||||
|
||||
/// `shortcuts.exportText` writes the set's name as the set was named, and a path that can't be
|
||||
/// written or isn't a string gives an error and writes nothing.
|
||||
#[test]
|
||||
fn export_text_command_writes_the_sets_name_and_rejects_a_bad_path() {
|
||||
type Files = std::rc::Rc<std::cell::RefCell<Vec<(String, String)>>>;
|
||||
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
|
||||
let written: Files = Default::default();
|
||||
let w = written.clone();
|
||||
app.services.write = Some(Box::new(move |path: &str, b: &[u8]| {
|
||||
if path.starts_with("/missing/") {
|
||||
return Err(format!("can't write {path}"));
|
||||
}
|
||||
w.borrow_mut().push((path.to_string(), String::from_utf8(b.to_vec()).map_err(|e| e.to_string())?));
|
||||
Ok(())
|
||||
}));
|
||||
app.run("shortcuts.import", json!({"data": export_json("Studio", &Overrides::new())})).unwrap();
|
||||
assert_eq!(app.run("shortcuts.exportText", json!({"path": "/sets/Studio.txt"})), Ok(json!({"path": "/sets/Studio.txt"})));
|
||||
assert_eq!(
|
||||
app.run("shortcuts.exportText", json!({"path": "/missing/dir/Studio.txt"})),
|
||||
Err("can't write /missing/dir/Studio.txt".to_string())
|
||||
);
|
||||
assert_eq!(app.run("shortcuts.exportText", json!({"path": 5})), Err("`path` must be a string".to_string()));
|
||||
let files = written.borrow();
|
||||
let [(path, text)] = files.as_slice() else { panic!("{files:?}") };
|
||||
assert_eq!(path, "/sets/Studio.txt");
|
||||
assert!(text.starts_with("Keyboard Shortcuts\nSet: Studio\n\nTools\n"), "{text}");
|
||||
assert_eq!(*text, export_text("Studio", &Overrides::new()));
|
||||
}
|
||||
|
||||
/// The dialog's Import… leaves an action its function key when the imported set gives the key
|
||||
/// to a command, through both Cancel and OK.
|
||||
#[test]
|
||||
|
||||
@@ -405,6 +405,38 @@ fn keyboard_shortcuts_import_and_export_ask_off_the_ui_thread() {
|
||||
assert_eq!(*written.borrow(), ["/keys/out.json", "/keys/command.json"]);
|
||||
}
|
||||
|
||||
/// The Keyboard Shortcuts dialog's Export Text… asks off the UI thread for a `.txt` file and writes
|
||||
/// the dialog's working set, as edited so far, as text where the dialog answers.
|
||||
#[test]
|
||||
fn keyboard_shortcuts_export_text_writes_the_working_set_as_text() {
|
||||
let (mut app, shown, _) = app();
|
||||
let texts: Rc<RefCell<Vec<(String, String)>>> = Default::default();
|
||||
let t = texts.clone();
|
||||
app.services.write = Some(Box::new(move |path: &str, b: &[u8]| {
|
||||
t.borrow_mut().push((path.to_string(), String::from_utf8_lossy(b).into_owned()));
|
||||
Ok(())
|
||||
}));
|
||||
let ov = crate::keymap::overrides_from(&[("view.grid", "Ctrl+Alt+G")]);
|
||||
app.run("edit.keyboardShortcuts", json!({})).unwrap();
|
||||
let d = app.ui.dialog.as_mut().expect("Keyboard Shortcuts");
|
||||
d.fields.insert("overrides".into(), crate::keymap::stored::to_value(&ov));
|
||||
d.fields.insert("set".into(), json!("Custom"));
|
||||
click(&mut app, "Export Text…", dialogs);
|
||||
match shown.requests().as_slice() {
|
||||
[PickRequest::Save(pick)] => assert_eq!(pick.filters, FilePick::filters([("Text", &["txt"][..])])),
|
||||
other => panic!("{other:?}"),
|
||||
}
|
||||
shown.answer(&["/keys/list.txt"]);
|
||||
poll(&mut app);
|
||||
let texts = texts.borrow();
|
||||
let [(path, text)] = texts.as_slice() else { panic!("{texts:?}") };
|
||||
assert_eq!(path, "/keys/list.txt");
|
||||
assert_eq!(*text, crate::shortcut_editor::export_text("Custom", &ov));
|
||||
assert!(text.contains(&format!("\t{}\n", crate::menus::pretty_shortcut("Ctrl+Alt+G"))), "{text}");
|
||||
assert!(app.ui.shortcut_overrides.is_empty(), "the working set is kept only on OK");
|
||||
assert_eq!(app.ui.dialog.as_ref().map(|d| d.kind.as_str()), Some("shortcuts"), "the dialog stays open");
|
||||
}
|
||||
|
||||
/// Keyboard Shortcuts' Import… opens a shortcut set another app saved as text (`.kys`) in Import
|
||||
/// Shortcut Set over the dialog when its file dialog answers, and the dialog's working set stays in
|
||||
/// Keyboard Shortcuts, which Cancel shows again.
|
||||
|
||||
@@ -88,6 +88,8 @@ fn save_panels_show_the_file_type_they_write() {
|
||||
assert_eq!(last_shown(&shown), FilePick::filters([("PostScript", &["ps"][..])]), "Print to a PostScript file");
|
||||
app.run("shortcuts.export", json!({})).unwrap();
|
||||
assert_eq!(last_shown(&shown), FilePick::filters([("Shortcut sets", &["json"][..])]), "Keyboard Shortcuts › Export…");
|
||||
app.run("shortcuts.exportText", json!({})).unwrap();
|
||||
assert_eq!(last_shown(&shown), FilePick::filters([("Text", &["txt"][..])]), "Keyboard Shortcuts › Export Text…");
|
||||
let presets = [
|
||||
("pdf.preset.save", json!({"name": "Mine"}), "pdf.preset.export", "PDF presets", pdfcmds::PRESET_EXTS),
|
||||
("print.presets.save", json!({"name": "Mine"}), "print.presets.export", "Print presets", printpresets::PRESET_EXTS),
|
||||
|
||||
+14
@@ -3401,6 +3401,20 @@ They list such a command while the user has changed its shortcut (`overridden: t
|
||||
shortcut for that command runs what a click on the item runs: Object › Path › Clean Up…, Print Ink Fixes… and Edit ›
|
||||
Find and Replace… open their dialogs.
|
||||
|
||||
`shortcuts.exportText {path?}` saves the current set's shortcut list as a UTF-8 text file, as Edit › Keyboard
|
||||
Shortcuts › Export Text… does with the dialog's set as edited so far. The file starts with a "Keyboard Shortcuts" line
|
||||
and a "Set:" line with the set's name, followed by a Tools section and a Menu Commands section. Each section lists the
|
||||
rows Edit › Keyboard Shortcuts lists, in its order and with names as it shows them: one line per row, with the name, a
|
||||
tab and the shortcuts as the dialog shows them on the current platform. A row with no shortcut ends after the tab.
|
||||
Without `path` a save dialog asks for the file. A `path` that is not a string, or a file that cannot be written,
|
||||
returns an error, and nothing is written. The layout is VectorCraft's own. The reference app's [Export keyboard
|
||||
shortcuts list as a text document](https://helpx.adobe.com/illustrator/desktop/get-started/preferences-and-settings/export-keyboard-shortcuts-list.html)
|
||||
page describes saving the list from the Keyboard Shortcuts dialog as a text file, and does not describe its layout.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"shortcuts.exportText","params":{"path":"/Users/me/Shortcuts.txt"}}}
|
||||
```
|
||||
|
||||
The desktop app adds its active artboard, the one the Artboards panel highlights, to the `object.align`,
|
||||
`object.distribute`, `object.distributeSpacing` and `select.allOnArtboard` calls it runs without `artboard`, as it does
|
||||
for `edit.pasteInPlace`, `edit.pasteInFront` and `edit.pasteInBack`, and to each `command.batch`. A batch passes its
|
||||
|
||||
@@ -765,6 +765,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- 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.
|
||||
- Shortcut sets other apps save as text (`.kys`) open in Import Shortcut Set from File › Open, from Edit › Keyboard Shortcuts › Import… in the desktop app, or from a drop on the window. It matches each entry to a tool, command or panel by name and decodes the file's key and modifier codes where VectorCraft's default shortcuts agree on them; the user answers the rest, and Apply fills the Keyboard Shortcuts dialog's working set. The answers are kept with the preferences for the next import (`shortcutSet.read`, `importMatches.*`).
|
||||
- Edit › Keyboard Shortcuts › Export Text… saves the set shown in the dialog as a UTF-8 text file, as the reference app's [Export keyboard shortcuts list as a text document](https://helpx.adobe.com/illustrator/desktop/get-started/preferences-and-settings/export-keyboard-shortcuts-list.html) page describes (`shortcuts.exportText {path?}`). The layout is VectorCraft's own: the set's name, then the Tools and Menu Commands rows in the dialog's order, each with its name, a tab and its shortcuts as the dialog shows them, and nothing after the tab for a row with no shortcut. Tests `shortcut_editor::tests::export_text_*` and `tests::picks::keyboard_shortcuts_export_text_writes_the_working_set_as_text`.
|
||||
- On Windows and Linux the app bar is the window's title bar (its own minimize, maximize and close buttons, drag to move, edges to resize), with the dragon app icon as the brand mark; dialogs and menus size to their content. As on a native menu bar, once one menu is open, moving the pointer onto another title opens that one.
|
||||
- Edit › Keyboard Shortcuts lists items of the menu bar and panel menus, as the reference app's [Customize keyboard shortcuts](https://web.archive.org/web/20221205131209id_/https://helpx.adobe.com/illustrator/using/customizing-keyboard-shortcuts.html) page describes for its Menu Commands. A menu command with no default shortcut that needs a value a key press does not give, such as File › Document Setup › Units (`document.setUnits {units}`), is listed only while the user has changed its shortcut. A command stays listed when a menu bar item runs it without a value or when it opens a dialog run without one, as the Variables panel's commands do.
|
||||
- A shortcut on the key left of 1 runs whatever character that key types, and Edit › Keyboard Shortcuts, the menus in the window, the command palette and tool tips show it as that character once the key has been pressed: `"` on a Turkish Q layout, `~` on a US layout as before. Shortcuts saved as `~` keep working (#4559).
|
||||
|
||||
Reference in New Issue
Block a user