Document: Cmd+Alt+Shift+U switches to the next unit of measurement

The reference app switches the units of measurement with
Ctrl+Alt+Shift+U on Windows and Option+Shift+Command+U on macOS.
VectorCraft could set the document's units with document.setUnits or
a right-click on a ruler, but no command stepped through them and no
key did it.

document.switchUnits (Switch Units, default Cmd+Alt+Shift+U) sets the
document's units to the next one in the order a right-click on a
ruler lists them: Points, Picas, Inches, Millimeters, Centimeters,
Pixels, Feet & Inches, Meters, Yards, Feet, and from Feet back to
Points. Each press is one undo step, and the reply names the new
units. Keyboard Shortcuts lists it under Document.

The precise cursors shortcut-editor test used Cmd+Alt+Shift+U as a
free key; it now uses Cmd+Alt+Shift+Q.

Docs: docs/mcp.md, docs/ui-parity.md, docs/target-app-parity.md.
This commit is contained in:
dotCooCoo
2026-10-29 10:02:27 +07:00
committed by bflatastic
parent a4ba07dd1b
commit 7bc7ea58b5
31 changed files with 104 additions and 2 deletions
+17
View File
@@ -42,6 +42,15 @@ pub fn specs() -> Vec<CommandSpec> {
has_doc,
set_units
),
cmd!(
"document.switchUnits",
"Switch Units",
[],
Some("Cmd+Alt+Shift+U"),
"{} the document's units become the next of Points, Picas, Inches, Millimeters, Centimeters, Pixels, Feet & Inches, Meters, Yards and Feet (the order a right-click on a ruler lists them), Feet going back to Points; one undo step → {units}",
has_doc,
switch_units
),
cmd!(
query "document.rulerOrigin",
"Ruler Origin",
@@ -332,6 +341,14 @@ fn set_units(s: &mut Session, p: &Value) -> Result<Value> {
ok()
}
/// Switch Units: the unit after the document's in [`Unit::ALL`], wrapping around.
fn switch_units(s: &mut Session, _: &Value) -> Result<Value> {
let now = s.doc()?.doc.units;
let next = Unit::ALL.iter().position(|u| *u == now).and_then(|i| Unit::ALL.get((i + 1) % Unit::ALL.len())).copied().unwrap_or_default();
s.set_document_units(next)?;
Ok(json!({ "units": next.label() }))
}
/// The `artboard` param of the ruler origin commands: an artboard index, 0 when not given.
fn artboard_param(s: &Session, p: &Value, c: &str) -> Result<usize> {
let index = match p.get("artboard") {
+22
View File
@@ -130,6 +130,28 @@ fn set_units_is_an_alias() {
assert!(s.execute("document.setUnits", &json!({"units": "parsecs"})).is_err());
}
/// Switch Units (Cmd+Alt+Shift+U) steps the document's units through every unit in the order a
/// right-click on a ruler lists them, Feet going back to Points, one undo step each.
#[test]
fn switch_units_steps_through_the_units_and_wraps() {
let spec = command_specs().iter().find(|c| c.id == "document.switchUnits").expect("registered");
assert_eq!((spec.label, spec.shortcut), ("Switch Units", Some("Cmd+Alt+Shift+U")));
assert!(Session::new().execute("document.switchUnits", &json!({})).is_err(), "no document");
let mut s = session();
assert_eq!(s.doc().unwrap().doc.units, Unit::Points);
let order = ["Picas", "Inches", "Millimeters", "Centimeters", "Pixels", "Feet & Inches", "Meters", "Yards", "Feet", "Points"];
for (i, label) in order.iter().enumerate() {
assert_eq!(s.execute("document.switchUnits", &json!({})).unwrap(), json!({"units": label}));
assert_eq!(s.doc().unwrap().doc.units.label(), *label);
assert_eq!(s.doc().unwrap().history.undo.len(), i + 1, "one undo step each");
}
s.execute("document.setUnits", &json!({"units": "Feet"})).unwrap();
s.execute("document.switchUnits", &json!({})).unwrap();
assert_eq!(s.doc().unwrap().doc.units, Unit::Points, "after Feet comes Points");
s.execute("edit.undo", &json!({})).unwrap();
assert_eq!(s.doc().unwrap().doc.units, Unit::Feet);
}
#[test]
fn language_picks_its_quotes_unless_quotes_are_given() {
let mut s = session();
+1
View File
@@ -3156,6 +3156,7 @@ font-technology Variable Променливи
Swatch Options… Опции на образец…
Swatch Tiles Плочки на образец
Swatches Образци
Switch Units Превключване на мерните единици
Switch workspace Превключване на работната среда
Add Content Добавяне на съдържание
Click to apply to the selected type Щракнете, за да приложите към избрания текст
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -71,6 +71,7 @@
Check Script Zkontrolovat skript
Other Script… Jiný skript…
Document Setup… Nastavení dokumentu…
Switch Units Přepnout jednotky
Document Color Mode Barevný režim dokumentu
CMYK Color Barvy CMYK
RGB Color Barvy RGB
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -57,6 +57,7 @@
Check Script Kontrollér script
Other Script… Andet script…
Document Setup… Dokumentopsætning…
Switch Units Skift enheder
Document Color Mode Dokumentets farvetilstand
CMYK Color CMYK-farve
RGB Color RGB-farve
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3194,6 +3194,7 @@ effect Points Punkte
Swatch Options… Farbfeldoptionen…
Swatch Tiles Farbfeldkacheln
Swatches Farbfelder
Switch Units Einheiten wechseln
Switch workspace Arbeitsbereich wechseln
Add Content Inhalt hinzufügen
Click to apply to the selected type Klicken, um auf den ausgewählten Text anzuwenden
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3569,6 +3569,7 @@ theme Appearance Εμφάνιση
Swatch Options Επιλογές δείγματος χρώματος
Swatch Options… Επιλογές δείγματος χρώματος…
Swatch Tiles Πλακίδια δειγμάτων χρωμάτων
Switch Units Αλλαγή μονάδων
Switch workspace Αλλαγή χώρου εργασίας
Add Content Προσθήκη περιεχομένου
Click to apply to the selected type Κλικ για εφαρμογή στο επιλεγμένο κείμενο
Can't render this file because it contains an unexpected character in line 2070 and column 19.
+1
View File
@@ -3224,6 +3224,7 @@ font-technology Variable Variables
Swatch Options… Opciones de muestra…
Swatch Tiles Mosaicos de muestras
Swatches Muestras
Switch Units Cambiar unidades
Switch workspace Cambiar espacio de trabajo
Add Content Añadir contenido
Click to apply to the selected type Haz clic para aplicarlo al texto seleccionado
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -79,6 +79,7 @@
Check Script Tarkista komentosarja
Other Script… Muu komentosarja…
Document Setup… Asiakirjan asetukset…
Switch Units Vaihda yksiköitä
Document Color Mode Asiakirjan väritila
CMYK Color CMYK-väri
RGB Color RGB-väri
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3221,6 +3221,7 @@ font-technology Variable Variables
Swatch Options… Options de nuance…
Swatch Tiles Carreaux de nuances
Swatches Nuancier
Switch Units Changer d’unités
Switch workspace Changer d’espace de travail
Add Content Ajouter du contenu
Click to apply to the selected type Cliquez pour l’appliquer au texte sélectionné
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3897,6 +3897,7 @@ mark-style Japanese Japán
Swatch Options… Színminta beállításai…
Swatch Tiles Színmintacsempék
Swatches Színminták
Switch Units Mértékegységek váltása
Switch workspace Munkaterület váltása
Symbol Szimbólum
Symbol Instance Szimbólumpéldány
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -57,6 +57,7 @@
Check Script Periksa skrip
Other Script… Skrip lain…
Document Setup… Pengaturan dokumen…
Switch Units Ganti satuan
Document Color Mode Mode warna dokumen
CMYK Color Warna CMYK
RGB Color Warna RGB
1 # Indonesian (id) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
57
58
59
60
61
62
63
+1
View File
@@ -3258,6 +3258,7 @@ mark-style Japanese Giapponese
Swatch Options… Opzioni campione…
Swatch Tiles Riquadri campioni
Swatches Campioni
Switch Units Cambia unità
Switch workspace Cambia area di lavoro
Add Content Aggiungi contenuto
Click to apply to the selected type Fai clic per applicarlo al testo selezionato
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2981,6 +2981,7 @@ mark-style Japanese 日本式
Swatch Options スウォッチオプション
Swatch Options… スウォッチオプション…
Swatch Tiles スウォッチタイル
Switch Units 単位を切り替え
Switch workspace ワークスペースを切り替え
Add Content コンテンツを追加
Click to apply to the selected type クリックして選択したテキストに適用
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -61,6 +61,7 @@
Scripts სკრიპტები
Other Script… სხვა სკრიპტი…
Document Setup… დოკუმენტის პარამეტრები…
Switch Units ერთეულების გადართვა
Document Color Mode დოკუმენტის ფერის რეჟიმი
CMYK Color CMYK ფერი
RGB Color RGB ფერი
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2975,6 +2975,7 @@ mark-style Japanese 일본식
Swatch Options 견본 옵션
Swatch Options… 견본 옵션…
Swatch Tiles 견본 타일
Switch Units 단위 전환
Switch workspace 작업 영역 전환
Add Content 콘텐츠 추가
Click to apply to the selected type 클릭하면 선택한 문자에 적용
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -57,6 +57,7 @@
Check Script Script controleren
Other Script… Ander script…
Document Setup… Documentinstellingen…
Switch Units Eenheden wisselen
Document Color Mode Documentkleurmodus
CMYK Color CMYK-kleur
RGB Color RGB-kleur
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -74,6 +74,7 @@
Check Script Sprawdź skrypt
Other Script… Inny skrypt…
Document Setup… Ustawienia dokumentu…
Switch Units Przełącz jednostki
Document Color Mode Tryb koloru dokumentu
CMYK Color Kolor CMYK
RGB Color Kolor RGB
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2660,6 +2660,7 @@
Swatch Tiles Blocos de Amostra
Swatch exchange files keep solid colors only. Arquivos de intercâmbio de amostras mantêm apenas cores sólidas.
Swatches Amostras
Switch Units Trocar Unidades
Switch workspace Trocar espaço de trabalho
Symbol Instance Instância de Símbolo
Symbol Libraries Bibliotecas de Símbolos
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -3254,6 +3254,7 @@ mark-style Japanese Японский
Swatch Options… Параметры образца…
Swatch Tiles Плитки образцов
Swatches Образцы
Switch Units Переключить единицы
Switch workspace Переключить рабочую среду
Add Content Добавить содержимое
Click to apply to the selected type Щёлкните, чтобы применить к выделенному тексту
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3156,6 +3156,7 @@ font-technology Variable Variabla
Swatch Options… Färgrutealternativ…
Swatch Tiles Rutvy för färgrutor
Swatches Färgrutor
Switch Units Byt enheter
Switch workspace Byt arbetslayout
Add Content Lägg till innehåll
Click to apply to the selected type Klicka för att använda på den markerade texten
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -3051,6 +3051,7 @@ font-technology Variable Değişken
Swatch Options… Renk Örneği Seçenekleri…
Swatch Tiles Renk Örneği Fayansları
Swatches Renk Örnekleri
Switch Units Birimleri değiştir
Switch workspace Çalışma alanını değiştir
Add Content İçerik Ekle
Click to apply to the selected type Seçilen türe uygulamak için tıklayın
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -3251,6 +3251,7 @@ effect Points Точки
Swatch Options… Параметри зразка…
Swatch Tiles Плитки зразків
Swatches Зразки
Switch Units Переключити одиниці
Switch workspace Переключити робоче середовище
Add Content Додати вміст
Click to apply to the selected type Клацніть, щоб застосувати до виділеного тексту
Can't render this file because it contains an unexpected character in line 749 and column 40.
+1
View File
@@ -3613,6 +3613,7 @@ mark-style Japanese Kiểu Nhật
Swatch Options… Tùy chọn mẫu màu…
Swatch Tiles Ô mẫu màu
Swatches Mẫu màu
Switch Units Chuyển đơn vị
Switch workspace Chuyển không gian làm việc
Switch x/y Đổi x/y
Symbol Instance Thực thể ký hiệu
1 # Vietnamese (vi) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
3613
3614
3615
3616
3617
3618
3619
+1
View File
@@ -3090,6 +3090,7 @@ font-script Japanese 汉字
Swatch Options… 色板选项…
Swatch Tiles 色板拼贴
Swatches 色板
Switch Units 切换单位
Switch workspace 切换工作区
Add Content 添加内容
Click to apply to the selected type 单击以应用到所选文字
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4031,6 +4031,7 @@ font-script Japanese 漢字
Swatch Options… 色票選項…
Swatch Tiles 色票拼貼
Swatches 色票
Switch Units 切換單位
Switch workspace 切換工作區
Add Content 新增內容
Click to apply to the selected type 按一下以套用到所選文字
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2 -2
View File
@@ -514,9 +514,9 @@ fn precise_cursors_command_is_listed_and_assignable_in_the_shortcut_editor() {
assert_eq!(ed::default_of("view.preciseCursors"), None, "no default key");
let mut overrides = craft_keymap::Overrides::new();
assert_eq!(ed::effective_in(&overrides, "view.preciseCursors"), None);
assert_eq!(ed::assign(&mut overrides, "view.preciseCursors", Some("Cmd+Alt+Shift+U"), false), Ok(vec![]));
assert_eq!(ed::assign(&mut overrides, "view.preciseCursors", Some("Cmd+Alt+Shift+Q"), false), Ok(vec![]));
let chord = ed::effective_in(&overrides, "view.preciseCursors").expect("assigned");
assert_eq!(ed::normalize(&chord), ed::normalize("Cmd+Alt+Shift+U"));
assert_eq!(ed::normalize(&chord), ed::normalize("Cmd+Alt+Shift+Q"));
// A key another command holds is refused, so the new command can't take it over silently.
assert!(ed::assign(&mut overrides, "view.preciseCursors", Some("Cmd+Alt+Shift+P"), false).is_err());
assert_eq!(ed::assign(&mut overrides, "view.preciseCursors", None, false), Ok(vec![]));
+32
View File
@@ -168,6 +168,38 @@ fn right_clicking_a_ruler_swaps_the_document_units() {
assert!(texts.iter().any(|(t, _)| t == "✓ Millimeters"), "the left ruler reflects the current unit: {texts:?}");
}
/// Cmd+Alt+Shift+U is Switch Units by default (Ctrl+Alt+Shift+U on Windows and Linux,
/// Option+Shift+Command+U on macOS): pressed, the document goes to the unit after its own in the
/// ruler's menu, and Smart Guides (Cmd+U) stay as they are. No other default has the key.
#[test]
fn cmd_alt_shift_u_switches_to_the_next_unit() {
use crate::shortcut_editor as ed;
use vectorcraft_doc::Unit;
assert_eq!(ed::default_command_shortcut("document.switchUnits"), Some("Cmd+Alt+Shift+U"));
assert_eq!(ed::command_for_key("Cmd+Alt+Shift+U"), Some("document.switchUnits"));
let shown = menus::pretty_shortcut("Cmd+Alt+Shift+U");
assert_eq!(shown, if cfg!(target_os = "macos") { "⌥⇧⌘U" } else { "Ctrl+Alt+Shift+U" });
let mut app = app();
let listed = app.run("shortcuts.list", json!({"query": "document.switchUnits"})).unwrap();
let rows: Vec<_> = listed.as_array().expect("rows").iter().map(|r| (r["label"].clone(), r["group"].clone(), r["default"].clone())).collect();
assert_eq!(rows, [(json!("Switch Units"), json!("Document"), json!("Cmd+Alt+Shift+U"))], "Keyboard Shortcuts lists it under Document");
assert_eq!(app.run("shortcuts.conflicts", json!({})).unwrap(), json!([]), "no other default has the key");
fn press(app: &mut VectorcraftApp) {
let ctx = egui::Context::default();
let modifiers = egui::Modifiers::COMMAND | egui::Modifiers::ALT | egui::Modifiers::SHIFT;
let ev = Event::Key { key: egui::Key::U, physical_key: None, pressed: true, repeat: false, modifiers };
let mut out = ctx.run_ui(egui::RawInput { events: vec![ev], ..Default::default() }, |ui| crate::shortcuts::handle(app, ui.ctx()));
out.textures_delta.clear();
}
let guides = app.ui.view.smart_guides;
press(&mut app);
assert_eq!(app.session.general_unit(), Unit::Picas, "Points → Picas");
assert_eq!(app.ui.view.smart_guides, guides, "Smart Guides stay as they are");
app.run("document.setUnits", json!({"units": "Feet"})).unwrap();
press(&mut app);
assert_eq!(app.session.general_unit(), Unit::Points, "Feet → Points");
}
fn labels(items: &[Item]) -> Vec<&'static str> {
items
.iter()
+3
View File
@@ -3075,6 +3075,9 @@ three: General (rulers, positions and sizes, the Info panel, dialog distances, c
(`document.inspect` → `units`): `document.setUnits {units}` (Document Setup) sets it for that document, and
`prefs.set {key: "unitsGeneral", value}` sets it for the active document too (one undo step) and is the units
`file.new` starts in when it gets no `units`. Stroke and Type are the preferences `unitsStroke` and `unitsType`.
`document.switchUnits` (Cmd/Ctrl+Alt+Shift+U) sets the active document's units to the next unit in the order a
right-click on a ruler lists them (Points, Picas, Inches, Millimeters, Centimeters, Pixels, Feet & Inches, Meters,
Yards, Feet, then Points again), in one undo step, and replies `{units}`.
`numbersWithoutUnitsArePoints` (on by default) makes the desktop app's length fields in picas read a number typed
with no unit in points (`12` is 12 pt, `2p6` and `1p` stay picas, `12 mm` millimetres); off, it is in picas. Fields in
other units read it in their unit either way, and the Preferences dialog dims the option unless a unit is Picas.
+1
View File
@@ -610,6 +610,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- 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+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+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.*`).
- 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.
- On Windows a maximized window stays inside the work area with the taskbar on any edge (#3242, #3723).
+3
View File
@@ -255,6 +255,9 @@ Cmd/Ctrl+Alt+N (`file.newWithoutDialog`, New Without Dialog in the shortcut edit
settings the New Document dialog opens on (the first Recent entry, or the Print category's Letter while Recent is
empty), without opening the dialog.
Cmd/Ctrl+Alt+Shift+U (`document.switchUnits`, Switch Units in the shortcut editor) switches the document to the
next unit in the order a right-click on a ruler lists them, from Feet back to Points.
## Panels, Control bar, Properties, context menus
| Interaction | Status | Evidence |