File: Cmd+Alt+N makes a new document without the New Document dialog

The reference app makes a document without opening the New Document
dialog with Ctrl+Alt+N on Windows and Option+Command+N on macOS.
VectorCraft had no default key for it.

file.newWithoutDialog (New Without Dialog, default Cmd+Alt+N) makes a
document with the settings New Document opens on: the first Recent
entry, or the Print category's Letter while Recent is empty, named
after the next untitled document. It fills the fields with the
dialog's own open, runs file.new with the params Create sends, and
does not show the dialog. A dialog that is already open stays open.
Keyboard Shortcuts lists it under File.

Docs: docs/mcp.md, docs/ui-parity.md, docs/target-app-parity.md.
This commit is contained in:
dotCooCoo
2026-10-21 15:42:36 +07:00
committed by bflatastic
parent f43c6ff47d
commit 156bd632e6
30 changed files with 117 additions and 6 deletions
+1 -1
View File
@@ -122,7 +122,7 @@ pub(crate) use export_for_screens::{
};
pub(crate) use form::{humanize, number_list_text, read_number_list, unit_suffix};
pub(crate) use new_document::preset_name;
pub use new_document::{open as open_new_document, preset_card};
pub use new_document::{create_without_dialog as new_document_without_dialog, open as open_new_document, preset_card};
pub use png_options::open as open_raster_options;
pub use save_pdf::{open as open_save_pdf, open_preset as open_pdf_preset};
pub use tools::open_tool_dialog;
+22 -5
View File
@@ -117,11 +117,7 @@ fn sync(app: &VectorcraftApp, d: &mut Dialog) {
/// Create the document; the dialog stays open when that fails (bad size, …).
fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
let mut p: Map<String, Value> = PARAMS.iter().filter_map(|k| Some((k.to_string(), d.fields.get(*k)?.clone()))).collect();
// Recent entries such as "Custom" aren't presets file.new knows.
if newdoc::find(&app.session, &d.str("preset")).is_none() {
p.remove("preset");
}
let p = params(app, d);
let r = app.run("file.new", Value::Object(p));
if r.is_ok() {
app.ui.dialog = None;
@@ -129,6 +125,27 @@ fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
r
}
/// New Without Dialog (`file.newWithoutDialog`, Cmd+Alt+N): create the document [`open`] would
/// offer, as its Create would, without showing the dialog. A dialog already open stays open.
pub fn create_without_dialog(app: &mut VectorcraftApp) -> Result<Value, String> {
let shown = app.ui.dialog.take();
open(app);
let offered = app.ui.dialog.take();
app.ui.dialog = shown;
let p = offered.map(|d| params(app, &d)).unwrap_or_default();
app.run("file.new", Value::Object(p))
}
/// The `file.new` params of the fields.
fn params(app: &VectorcraftApp, d: &Dialog) -> Map<String, Value> {
let mut p: Map<String, Value> = PARAMS.iter().filter_map(|k| Some((k.to_string(), d.fields.get(*k)?.clone()))).collect();
// Recent entries such as "Custom" aren't presets file.new knows.
if newdoc::find(&app.session, &d.str("preset")).is_none() {
p.remove("preset");
}
p
}
/// The units the size fields show.
fn unit(d: &Dialog) -> Unit {
Unit::named(&d.str("units")).unwrap_or_default()
+1
View File
@@ -1925,6 +1925,7 @@
New View Нов изглед
New View… Нов изглед…
New Window Нов прозорец
New Without Dialog Нов без диалогов прозорец
New Workspace Ново работно пространство
New Workspace… Ново работно пространство…
New {kind} Style… Нов стил ({kind})…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -36,6 +36,7 @@
Quit VectorCraft Ukončit VectorCraft
File Soubor
New… Nový…
New Without Dialog Nový bez dialogového okna
New from Template… Nový ze šablony…
Open… Otevřít…
Open Recent Files Otevřít nedávné soubory
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -22,6 +22,7 @@
Quit VectorCraft Slut VectorCraft
File Filer
New… Ny…
New Without Dialog Ny uden dialog
New from Template… Ny fra skabelon…
Open… Åbn…
Open Recent Files Åbn seneste filer
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1943,6 +1943,7 @@ file-filter Templates Vorlagen
New View Neue Ansicht
New View… Neue Ansicht…
New Window Neues Fenster
New Without Dialog Neu ohne Dialogfeld
New Workspace Neuer Arbeitsbereich
New Workspace… Neuer Arbeitsbereich…
New {kind} Style… Neues {kind}format…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1624,6 +1624,7 @@
New Layer… Νέο επίπεδο…
New Swatch… Νέο δείγμα χρώματος…
New Window Νέο παράθυρο
New Without Dialog Νέο χωρίς παράθυρο διαλόγου
New Workspace Νέος χώρος εργασίας
New Workspace… Νέος χώρος εργασίας…
New… Νέο…
1 # Ελληνικά (el) — VectorCraft
1624
1625
1626
1627
1628
1629
1630
+1
View File
@@ -1968,6 +1968,7 @@
New View Nueva vista
New View… Nueva vista…
New Window Nueva ventana
New Without Dialog Nuevo sin cuadro de diálogo
New Workspace Nuevo espacio de trabajo
New Workspace… Nuevo espacio de trabajo…
New {kind} Style… Nuevo estilo de {kind}…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -44,6 +44,7 @@
Quit VectorCraft Lopeta VectorCraft
File Tiedosto
New… Uusi…
New Without Dialog Uusi ilman valintaikkunaa
New from Template… Uusi mallipohjasta…
Open… Avaa…
Open Recent Files Avaa viimeisimmät tiedostot
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1965,6 +1965,7 @@
New View Nouvelle vue
New View… Nouvelle vue…
New Window Nouvelle fenêtre
New Without Dialog Nouveau sans boîte de dialogue
New Workspace Nouvel espace de travail
New Workspace… Nouvel espace de travail…
New {kind} Style… Nouveau style de {kind}…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2418,6 +2418,7 @@ file-filter Templates Sablonok
New View Új nézet
New View… Új nézet…
New Window Új ablak
New Without Dialog Új párbeszédablak nélkül
New Workspace Új munkaterület
New Workspace… Új munkaterület…
New {kind} Style… Új stílus: {kind}…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -22,6 +22,7 @@
Quit VectorCraft Keluar dari VectorCraft
File Berkas
New… Baru…
New Without Dialog Baru tanpa dialog
New from Template… Baru dari templat…
Open… Buka…
Open Recent Files Buka berkas terbaru
1 # Indonesian (id) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
22
23
24
25
26
27
28
+1
View File
@@ -1994,6 +1994,7 @@ file-filter Templates Modelli
New View Nuova vista
New View… Nuova vista…
New Window Nuova finestra
New Without Dialog Nuovo senza finestra di dialogo
New Workspace Nuova area di lavoro
New Workspace… Nuova area di lavoro…
New {kind} Style… Nuovo stile {kind}…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -73,6 +73,7 @@
Quit VectorCraft VectorCraft を終了
File ファイル
New… 新規…
New Without Dialog ダイアログなしで新規
New from Template… テンプレートから新規…
Open… 開く…
Open Recent Files 最近使用したファイルを開く
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -29,6 +29,7 @@
Quit VectorCraft VectorCraft-იდან გასვლა
File ფაილი
New… ახალი…
New Without Dialog ახალი დიალოგის გარეშე
New from Template… შაბლონიდან შექმნა…
Open… გახსნა…
Open Recent Files ბოლოს გახსნილი ფაილების გახსნა
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -69,6 +69,7 @@
Quit VectorCraft VectorCraft 종료
File 파일
New… 새로 만들기…
New Without Dialog 대화상자 없이 새로 만들기
New from Template… 템플릿에서 새로 만들기…
Open… 열기…
Open Recent Files 최근 파일 열기
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -22,6 +22,7 @@
Quit VectorCraft VectorCraft afsluiten
File Bestand
New… Nieuw…
New Without Dialog Nieuw zonder dialoogvenster
New from Template… Nieuw van sjabloon…
Open… Openen…
Open Recent Files Recente bestanden openen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -40,6 +40,7 @@
Quit VectorCraft Zakończ VectorCraft
File Plik
New… Nowy…
New Without Dialog Nowy bez okna dialogowego
New from Template… Nowy z szablonu…
Open… Otwórz…
Open Recent Files Otwórz ostatnie pliki
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1604,6 +1604,7 @@
New Symbol… Novo Símbolo…
New View… Nova Visualização…
New Window Nova Janela
New Without Dialog Novo sem Diálogo
New Workspace Novo Espaço de Trabalho
New Workspace… Novo Espaço de Trabalho…
New file Novo arquivo
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -1990,6 +1990,7 @@ file-filter Templates Шаблоны
New View Новый вид
New View… Новый вид…
New Window Новое окно
New Without Dialog Создать без диалогового окна
New Workspace Новая рабочая среда
New Workspace… Новая рабочая среда…
New {kind} Style… Новый стиль {kind}…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1925,6 +1925,7 @@
New View Ny vy
New View… Ny vy…
New Window Nytt fönster
New Without Dialog Ny utan dialogruta
New Workspace Ny arbetsyta
New Workspace… Ny arbetsyta…
New {kind} Style… Ny {kind}stil…
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -1986,6 +1986,7 @@ file-filter Templates Шаблони
New View Новий вигляд
New View… Новий вигляд…
New Window Нове вікно
New Without Dialog Створити без діалогового вікна
New Workspace Нове робоче середовище
New Workspace… Нове робоче середовище…
New {kind} Style… Новий стиль {kind}…
Can't render this file because it contains an unexpected character in line 725 and column 40.
+1
View File
@@ -2226,6 +2226,7 @@ file-filter Templates Mẫu
New View Chế độ xem mới
New View… Chế độ xem mới…
New Window Cửa sổ mới
New Without Dialog Mới không qua hộp thoại
New Workspace Không gian làm việc mới
New Workspace… Không gian làm việc mới…
New {kind} Style… Kiểu {kind} mới…
1 # Vietnamese (vi) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
2226
2227
2228
2229
2230
2231
2232
+1
View File
@@ -1884,6 +1884,7 @@ file-filter Templates 模板
New View 新建视图
New View… 新建视图…
New Window 新建窗口
New Without Dialog 无对话框新建
New Workspace 新建工作区
New Workspace… 新建工作区…
New {kind} Style… 新建{kind}样式…
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2711,6 +2711,7 @@ file-filter Templates 範本
New View 新增檢視
New View… 新增檢視…
New Window 新增視窗
New Without Dialog 新增但不開啟對話方塊
New Workspace 新增工作區
New Workspace… 新增工作區…
New {kind} Style… 新增{kind}樣式…
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -166,6 +166,12 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
),
("file.documentSetup", "Document Setup…", "Cmd+Alt+P", "{}"),
("file.newDialog", "New…", "Cmd+N", "{} opens the New Document dialog"),
(
"file.newWithoutDialog",
"New Without Dialog",
"Cmd+Alt+N",
"{} makes a document with the settings the New Document dialog opens on (the first Recent entry, else the Print category's Letter), named after the next untitled document, without opening the dialog → {index, previewMode}",
),
("app.home", "Home", "", "{} shows the Home screen (new file presets, Open) over the open documents; choosing a document tab returns to it"),
("edit.preferences", "Preferences…", "Cmd+K", "{category?} open Preferences (engine: prefs.get / prefs.set / prefs.list)"),
("edit.keyboardShortcuts", "Keyboard Shortcuts…", "Cmd+Alt+Shift+K", "{}"),
@@ -1105,6 +1111,7 @@ pub fn run_ui_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<R
crate::dialogs::open_new_document(app);
Ok(Value::Null)
}
"file.newWithoutDialog" => crate::dialogs::new_document_without_dialog(app),
"app.home" => {
app.ui.home = Some(home_key(app));
Ok(Value::Null)
+56
View File
@@ -91,6 +91,62 @@ fn cmd_n_opens_the_new_document_dialog() {
assert_eq!(app.session.documents().len(), 1, "no document is made until the dialog's OK");
}
/// Cmd+Alt+N is New Without Dialog by default: Ctrl+Alt+N on Windows and Linux, Option+Command+N
/// on macOS. No other command, tool or panel has that key by default.
#[test]
fn cmd_alt_n_is_new_without_dialog() {
assert_eq!(crate::shortcut_editor::default_command_shortcut("file.newWithoutDialog"), Some("Cmd+Alt+N"));
assert_eq!(crate::shortcut_editor::command_for_key("Cmd+Alt+N"), Some("file.newWithoutDialog"));
let chord = crate::shortcuts::parse("Cmd+Alt+N").expect("parses");
assert_eq!((chord.modifiers, chord.logical_key), (egui::Modifiers::COMMAND | egui::Modifiers::ALT, egui::Key::N));
let shown = crate::menus::pretty_shortcut("Cmd+Alt+N");
assert_eq!(shown, if cfg!(target_os = "macos") { "⌥⌘N" } else { "Ctrl+Alt+N" });
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), crate::Services::default());
let listed = app.run("shortcuts.list", json!({"query": "file.newWithoutDialog"})).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!("New Without Dialog"), json!("File"), json!("Cmd+Alt+N"))], "Keyboard Shortcuts lists it under File");
assert_eq!(app.run("shortcuts.conflicts", json!({})).unwrap(), json!([]), "no other default has the key");
}
/// Cmd+Alt+N, pressed through the shortcut handler, makes a document with the settings New
/// Document opens on (the Print category's Letter while Recent is empty, then the first Recent
/// entry), named as the dialog names it, and does not open the dialog.
#[test]
fn cmd_alt_n_makes_a_document_without_the_new_document_dialog() {
use vectorcraft_doc::ColorMode;
fn press(app: &mut VectorcraftApp) {
let ctx = egui::Context::default();
let modifiers = egui::Modifiers::COMMAND | egui::Modifiers::ALT;
let ev = egui::Event::Key { key: egui::Key::N, 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 made = |app: &VectorcraftApp| {
let d = &app.session.active().expect("a document").doc;
let r = d.artboards[0].rect;
(d.title.clone(), r.width(), r.height(), d.color_mode, d.raster_effects_ppi)
};
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), crate::Services::default());
assert!(app.session.active().is_none());
let name = app.session.peek_untitled();
press(&mut app);
assert_eq!(app.session.documents().len(), 1);
assert!(app.ui.dialog.is_none(), "the New Document dialog does not open");
assert_eq!(made(&app), (name, 612.0, 792.0, ColorMode::Cmyk, 300.0), "Letter from the Print category, as New Document opens on");
// Then the first Recent entry, the 400 × 300 pt document's settings.
app.run("file.new", json!({"width": 400, "height": 300})).unwrap();
let name = app.session.peek_untitled();
press(&mut app);
assert_eq!(app.session.documents().len(), 3);
assert!(app.ui.dialog.is_none());
assert_eq!(made(&app), (name, 400.0, 300.0, ColorMode::Rgb, 72.0));
// Run as a command while a dialog is open, it leaves that dialog open.
app.run("file.newDialog", json!({})).unwrap();
app.run("file.newWithoutDialog", json!({})).unwrap();
assert_eq!(app.session.documents().len(), 4);
assert_eq!(app.ui.dialog.as_ref().map(|d| d.kind.as_str()), Some("newDocument"));
}
/// One Home screen frame (no document open) with `events`: the texts drawn and where.
fn home_texts(app: &mut VectorcraftApp, ctx: &egui::Context, events: Vec<egui::Event>) -> Vec<(String, egui::Rect)> {
fn walk(s: &egui::Shape, out: &mut Vec<(String, egui::Rect)>) {
+3
View File
@@ -2619,6 +2619,9 @@ passed straight back to `file.new`. Print presets and sizes without `units` star
(mobile, web, video, social) in Pixels. A saved or Recent preset whose size (up to 163,830 pt), `artboards` (1 to
1,000), spacing (0 to 100,000 pt) or bleed (0 to 72 pt a side) lies outside those ranges is read with the nearer end of
each range, and a size of 0 or less is read as 1 pt.
The desktop app's `file.newDialog` (Cmd/Ctrl+N) opens the New Document dialog on the first Recent entry, or on the
Print category's Letter while Recent is empty. `file.newWithoutDialog` (Cmd/Ctrl+Alt+N) runs `file.new` with those
settings and the next untitled name, without opening the dialog, and returns what `file.new` returns.
```json
{"name":"run_command","arguments":{"command":"file.new","params":{"preset":"A4","orientation":"landscape","artboards":4,"artboardLayout":{"columns":2},"bleed":9}}}
+1
View File
@@ -516,6 +516,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- Cmd/Ctrl+Alt+Shift+. and , (`type.size.increaseByFive`, `type.size.decreaseByFive`) step the font size of the selected type, or of the text the Type tool has selected, by five times the Size/Leading increment (Preferences › Type); Cmd/Ctrl+Shift+. and , still step it by one increment.
- Cmd/Ctrl+Alt+Q (`type.resetTracking`) sets the tracking of the selected type, or of the text the Type tool has selected, to 0 and its kerning to Auto (0 in the Character panel), in one undo step; at a caret it resets the kerning of the character before it.
- 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 "Create a document without opening the 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.
- 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.
- **Tools:**
+4
View File
@@ -199,6 +199,10 @@ the type shortcuts (tracking/kerning/leading/baseline steps with Alt/Shift), and
Layers panel. The shortcut editor also lists the commands that are in no menu but run without parameters (Edit › Duplicate,
panel-menu commands such as Break Link to Symbol), so they can be given shortcuts (#1539). The [ and ] keys reach the Blob Brush, the Eraser and the Symbolism tools in the app (#1734, part of #1661).
Cmd/Ctrl+Alt+N (`file.newWithoutDialog`, New Without Dialog in the shortcut editor) makes a document with the
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.
## Panels, Control bar, Properties, context menus
| Behaviour | Status | Notes |