mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 20:27:05 -06:00
Merge pull request #4377 from dotCooCoo/feat/next-document-shortcut
Window: Cmd+F6 and Cmd+Shift+F6 go to the next and previous document
This commit is contained in:
@@ -29,7 +29,7 @@ pub use status_bar::status_bar;
|
||||
use status_bar::{StatusReadoutWidths, status_readouts};
|
||||
#[cfg(test)]
|
||||
use tabs::{CLOSE_BEFORE_TITLE, first_tab_shown, tab_title};
|
||||
pub use tabs::{doc_tabs, isolation_bar};
|
||||
pub use tabs::{doc_tabs, isolation_bar, step_document};
|
||||
|
||||
/// The application bar's height, in points (compact, as in PhotoCraft).
|
||||
pub const APP_BAR_HEIGHT: f32 = 32.0;
|
||||
|
||||
@@ -114,21 +114,47 @@ pub fn doc_tabs(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
app.status(e);
|
||||
}
|
||||
} else if let Some(i) = activate {
|
||||
app.ui.home = None;
|
||||
let changed = app.session.active_index() != Some(i);
|
||||
if app.session.set_active(i)
|
||||
&& changed
|
||||
&& app.session.tool_id() == "artboard"
|
||||
&& let Some(n) = app.session.active().map(|d| d.doc.artboards.len())
|
||||
{
|
||||
// A document switch recreates the tool; restore the displayed board as its target.
|
||||
// Clicking the current tab keeps its existing multiselection and tool options.
|
||||
let selected = crate::panels::artboards::selected(app, n);
|
||||
crate::panels::artboards::select(app, selected);
|
||||
}
|
||||
show_document(app, i);
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes document `i` the current one, as a click on its tab does: the Home screen closes, and
|
||||
/// with the Artboard tool the artboard the document shows becomes the tool's target.
|
||||
fn show_document(app: &mut VectorcraftApp, i: usize) {
|
||||
app.ui.home = None;
|
||||
let changed = app.session.active_index() != Some(i);
|
||||
if app.session.set_active(i)
|
||||
&& changed
|
||||
&& app.session.tool_id() == "artboard"
|
||||
&& let Some(n) = app.session.active().map(|d| d.doc.artboards.len())
|
||||
{
|
||||
// A document switch recreates the tool; restore the displayed board as its target.
|
||||
// Clicking the current tab keeps its existing multiselection and tool options.
|
||||
let selected = crate::panels::artboards::selected(app, n);
|
||||
crate::panels::artboards::select(app, selected);
|
||||
}
|
||||
}
|
||||
|
||||
/// `window.nextDocument` (`forward`) and `window.previousDocument`: makes the open document after
|
||||
/// the current one in tab order (before it) the current one, as a click on its tab does. After the
|
||||
/// last document comes the first, and before the first document comes the last. On the Home
|
||||
/// screen, where no tab is the current one, the next document is the first and the previous
|
||||
/// document is the last. Returns `{index}`.
|
||||
pub fn step_document(app: &mut VectorcraftApp, forward: bool) -> Result<serde_json::Value, String> {
|
||||
let n = app.session.documents().len();
|
||||
if n == 0 {
|
||||
return Err("no document open".into());
|
||||
}
|
||||
let i = match (app.session.active_index().filter(|_| app.ui.home.is_none()), forward) {
|
||||
(Some(a), true) => (a + 1) % n,
|
||||
(Some(a), false) => (a + n - 1) % n,
|
||||
(None, true) => 0,
|
||||
(None, false) => n - 1,
|
||||
};
|
||||
show_document(app, i);
|
||||
Ok(json!({ "index": i }))
|
||||
}
|
||||
|
||||
/// The isolation mode breadcrumb bar. It is drawn over the top of `area` (the canvas), after the
|
||||
/// canvas, so entering isolation mode does not change the canvas's size (#3126).
|
||||
pub fn isolation_bar(app: &mut VectorcraftApp, ui: &mut Ui, area: egui::Rect) {
|
||||
|
||||
@@ -1294,6 +1294,127 @@ fn artboard_document_tab_roundtrip_preserves_other_tools() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Press F6 with `modifiers` through the shortcut handler.
|
||||
fn press_f6(app: &mut crate::VectorcraftApp, modifiers: egui::Modifiers) {
|
||||
let ctx = egui::Context::default();
|
||||
let ev = egui::Event::Key { key: egui::Key::F6, 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();
|
||||
}
|
||||
|
||||
/// Cmd+F6 is Next Document and Cmd+Shift+F6 is Previous Document by default: Ctrl+F6 and
|
||||
/// Ctrl+Shift+F6 on Windows and Linux, Command+F6 and Shift+Command+F6 on macOS. Keyboard
|
||||
/// Shortcuts lists both under Window. F6 and Shift+F6 are still the Color and Appearance panels'
|
||||
/// keys, and no other command, tool or panel has either key by default.
|
||||
#[test]
|
||||
fn cmd_f6_and_cmd_shift_f6_are_next_and_previous_document() {
|
||||
use crate::shortcut_editor::{command_for_key, default_command_shortcut, panel_shortcut};
|
||||
assert_eq!(default_command_shortcut("window.nextDocument"), Some("Cmd+F6"));
|
||||
assert_eq!(default_command_shortcut("window.previousDocument"), Some("Cmd+Shift+F6"));
|
||||
assert_eq!(command_for_key("Cmd+F6"), Some("window.nextDocument"));
|
||||
assert_eq!(command_for_key("Cmd+Shift+F6"), Some("window.previousDocument"));
|
||||
assert_eq!((panel_shortcut("color"), panel_shortcut("appearance")), (Some("F6"), Some("Shift+F6")));
|
||||
let chord = crate::shortcuts::parse("Cmd+Shift+F6").expect("parses");
|
||||
assert_eq!((chord.modifiers, chord.logical_key), (egui::Modifiers::COMMAND | egui::Modifiers::SHIFT, egui::Key::F6));
|
||||
let shown = (crate::menus::pretty_shortcut("Cmd+F6"), crate::menus::pretty_shortcut("Cmd+Shift+F6"));
|
||||
let want = if cfg!(target_os = "macos") { ("⌘F6", "⇧⌘F6") } else { ("Ctrl+F6", "Ctrl+Shift+F6") };
|
||||
assert_eq!((shown.0.as_str(), shown.1.as_str()), want);
|
||||
let mut app = crate::VectorcraftApp::new(Session::new(), Default::default());
|
||||
let listed = app.run("shortcuts.list", json!({"query": "Document"})).unwrap();
|
||||
let rows: Vec<_> = listed
|
||||
.as_array()
|
||||
.expect("rows")
|
||||
.iter()
|
||||
.filter(|r| r["id"].as_str().is_some_and(|id| id.ends_with("Document") && id.starts_with("window.")))
|
||||
.map(|r| (r["label"].clone(), r["group"].clone(), r["default"].clone()))
|
||||
.collect();
|
||||
assert_eq!(
|
||||
rows,
|
||||
[(json!("Next Document"), json!("Window"), json!("Cmd+F6")), (json!("Previous Document"), json!("Window"), json!("Cmd+Shift+F6"))],
|
||||
"Keyboard Shortcuts lists both"
|
||||
);
|
||||
assert_eq!(app.run("shortcuts.conflicts", json!({})).unwrap(), json!([]), "no other default has the keys");
|
||||
}
|
||||
|
||||
/// Cmd+F6 makes the next open document in tab order the current one, and Cmd+Shift+F6 makes the
|
||||
/// previous one the current one. 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 and close the screen.
|
||||
/// With no document open the commands are disabled and fail with "no document open".
|
||||
#[test]
|
||||
fn cmd_f6_goes_to_the_next_document_and_cmd_shift_f6_to_the_previous_one() {
|
||||
let mut app = crate::VectorcraftApp::new(Session::new(), Default::default());
|
||||
assert!(!crate::menus::enabled(&app, "window.nextDocument") && !crate::menus::enabled(&app, "window.previousDocument"));
|
||||
assert_eq!(app.run("window.nextDocument", json!({})).unwrap_err(), "no document open");
|
||||
assert_eq!(app.run("window.previousDocument", json!({})).unwrap_err(), "no document open");
|
||||
for name in ["A", "B", "C"] {
|
||||
app.run("file.new", json!({"width": 100, "height": 100, "name": name})).unwrap();
|
||||
}
|
||||
assert!(crate::menus::enabled(&app, "window.nextDocument") && crate::menus::enabled(&app, "window.previousDocument"));
|
||||
assert_eq!(app.session.active_index(), Some(2));
|
||||
let mut seen = vec![];
|
||||
for modifiers in [egui::Modifiers::COMMAND; 4] {
|
||||
press_f6(&mut app, modifiers);
|
||||
seen.push(app.session.active_index());
|
||||
}
|
||||
assert_eq!(seen, [Some(0), Some(1), Some(2), Some(0)], "Cmd+F6 goes right and wraps from the last to the first");
|
||||
seen.clear();
|
||||
for modifiers in [egui::Modifiers::COMMAND | egui::Modifiers::SHIFT; 4] {
|
||||
press_f6(&mut app, modifiers);
|
||||
seen.push(app.session.active_index());
|
||||
}
|
||||
assert_eq!(seen, [Some(2), Some(1), Some(0), Some(2)], "Cmd+Shift+F6 goes left and wraps from the first to the last");
|
||||
assert_eq!(app.run("window.nextDocument", json!({})).unwrap(), json!({"index": 0}));
|
||||
assert_eq!(app.run("window.previousDocument", json!({})).unwrap(), json!({"index": 2}));
|
||||
app.session.set_active(1);
|
||||
app.run("app.home", json!({})).unwrap();
|
||||
press_f6(&mut app, egui::Modifiers::COMMAND);
|
||||
assert_eq!((app.session.active_index(), app.ui.home), (Some(0), None), "from the Home screen Cmd+F6 shows the first");
|
||||
app.session.set_active(1);
|
||||
app.run("app.home", json!({})).unwrap();
|
||||
press_f6(&mut app, egui::Modifiers::COMMAND | egui::Modifiers::SHIFT);
|
||||
assert_eq!((app.session.active_index(), app.ui.home), (Some(2), None), "and Cmd+Shift+F6 the last");
|
||||
// One document: the keys keep it current.
|
||||
let mut one = crate::VectorcraftApp::new(Session::new(), Default::default());
|
||||
one.run("file.new", json!({"width": 100, "height": 100})).unwrap();
|
||||
press_f6(&mut one, egui::Modifiers::COMMAND);
|
||||
press_f6(&mut one, egui::Modifiers::COMMAND | egui::Modifiers::SHIFT);
|
||||
assert_eq!(one.session.active_index(), Some(0));
|
||||
}
|
||||
|
||||
/// With the Artboard tool, Cmd+F6 and Cmd+Shift+F6 switch documents as a click on a tab does: the
|
||||
/// document switched back to keeps the artboard it shows as the tool's target, so the Properties
|
||||
/// panel's Delete Artboard then removes that artboard. Switching is not an edit.
|
||||
#[test]
|
||||
fn cmd_f6_switches_documents_as_a_tab_click_does_with_the_artboard_tool() {
|
||||
let (mut app, ctx) = artboard_document_app();
|
||||
app.select_tool("artboard");
|
||||
artboard_navigation_next(&mut app, &ctx);
|
||||
assert_eq!(app.session.tool_options()["selected"], json!([1]));
|
||||
let before = app.session.active().unwrap().doc.clone();
|
||||
let undo = app.session.active().unwrap().history.undo.len();
|
||||
press_f6(&mut app, egui::Modifiers::COMMAND);
|
||||
assert_eq!(app.session.active_index(), Some(1));
|
||||
// The app draws frames while the other document is the current one.
|
||||
artboard_navigation_properties_frame(&mut app, &ctx, vec![]);
|
||||
artboard_document_tabs_frame(&mut app, &ctx, vec![]);
|
||||
press_f6(&mut app, egui::Modifiers::COMMAND | egui::Modifiers::SHIFT);
|
||||
assert_eq!(app.session.active_index(), Some(0));
|
||||
app.sync_views();
|
||||
assert_eq!(app.session.tool_options()["selected"], json!([1]), "the tool targets the displayed artboard");
|
||||
assert_eq!(app.view().unwrap().artboard, 1, "the document keeps its displayed artboard");
|
||||
assert_eq!(app.session.active().unwrap().doc, before, "switching documents is not a document edit");
|
||||
assert_eq!(app.session.active().unwrap().history.undo.len(), undo);
|
||||
artboard_navigation_properties_frame(&mut app, &ctx, vec![]);
|
||||
let texts = artboard_navigation_properties_frame(&mut app, &ctx, vec![]);
|
||||
let at = texts.iter().find(|(label, _)| label == "Delete Artboard").map(|(_, r)| r.center()).expect("Properties Delete button");
|
||||
let button = |pressed| egui::Event::PointerButton { pos: at, button: egui::PointerButton::Primary, pressed, modifiers: Default::default() };
|
||||
for event in [egui::Event::PointerMoved(at), button(true), button(false)] {
|
||||
artboard_navigation_properties_frame(&mut app, &ctx, vec![event]);
|
||||
}
|
||||
let names: Vec<_> = app.session.active().unwrap().doc.artboards.iter().map(|a| a.name.clone()).collect();
|
||||
assert_eq!(names, ["Keep"], "Delete Artboard after the keys removes the artboard the document shows");
|
||||
}
|
||||
|
||||
/// One history entry: its label, document and selection.
|
||||
type HistoryRow = (String, Arc<vectorcraft_doc::Document>, Arc<vectorcraft_doc::Selection>);
|
||||
|
||||
|
||||
@@ -1991,6 +1991,8 @@ font-technology Variable Променливи
|
||||
New View Нов изглед
|
||||
New View… Нов изглед…
|
||||
New Window Нов прозорец
|
||||
Next Document Следващ документ
|
||||
Previous Document Предишен документ
|
||||
New Without Dialog Нов без диалогов прозорец
|
||||
New Workspace Ново работно пространство
|
||||
New Workspace… Ново работно пространство…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -625,6 +625,8 @@
|
||||
Saved View 25 Uložené zobrazení 25
|
||||
Window Okno
|
||||
New Window Nové okno
|
||||
Next Document Další dokument
|
||||
Previous Document Předchozí dokument
|
||||
Cascade Do kaskády
|
||||
Tile Vedle sebe
|
||||
Float in Window Uvolnit do samostatného okna
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -578,6 +578,8 @@
|
||||
Saved View 25 Gemt visning 25
|
||||
Window Vindue
|
||||
New Window Nyt vindue
|
||||
Next Document Næste dokument
|
||||
Previous Document Forrige dokument
|
||||
Cascade Kaskade
|
||||
Tile Fliselæg
|
||||
Float in Window Flyd i vindue
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2004,6 +2004,8 @@ file-filter Templates Vorlagen
|
||||
New View Neue Ansicht
|
||||
New View… Neue Ansicht…
|
||||
New Window Neues Fenster
|
||||
Next Document Nächstes Dokument
|
||||
Previous Document Vorheriges Dokument
|
||||
New Without Dialog Neu ohne Dialogfeld
|
||||
New Workspace Neuer Arbeitsbereich
|
||||
New Workspace… Neuer Arbeitsbereich…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1674,6 +1674,8 @@ font-technology Variable Μεταβλητές
|
||||
New Layer… Νέο επίπεδο…
|
||||
New Swatch… Νέο δείγμα χρώματος…
|
||||
New Window Νέο παράθυρο
|
||||
Next Document Επόμενο έγγραφο
|
||||
Previous Document Προηγούμενο έγγραφο
|
||||
New Without Dialog Νέο χωρίς παράθυρο διαλόγου
|
||||
New Workspace Νέος χώρος εργασίας
|
||||
New Workspace… Νέος χώρος εργασίας…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 164 and column 5.
|
@@ -2046,6 +2046,8 @@ font-technology Variable Variables
|
||||
New View Nueva vista
|
||||
New View… Nueva vista…
|
||||
New Window Nueva ventana
|
||||
Next Document Documento siguiente
|
||||
Previous Document Documento anterior
|
||||
New Without Dialog Nuevo sin cuadro de diálogo
|
||||
New Workspace Nuevo espacio de trabajo
|
||||
New Workspace… Nuevo espacio de trabajo…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -616,6 +616,8 @@
|
||||
Saved View 25 Tallennettu näkymä 25
|
||||
Window Ikkuna
|
||||
New Window Uusi ikkuna
|
||||
Next Document Seuraava asiakirja
|
||||
Previous Document Edellinen asiakirja
|
||||
Cascade Porrasta
|
||||
Tile Vierekkäin
|
||||
Float in Window Kelluta ikkunassa
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2043,6 +2043,8 @@ font-technology Variable Variables
|
||||
New View Nouvelle vue
|
||||
New View… Nouvelle vue…
|
||||
New Window Nouvelle fenêtre
|
||||
Next Document Document suivant
|
||||
Previous Document Document précédent
|
||||
New Without Dialog Nouveau sans boîte de dialogue
|
||||
New Workspace Nouvel espace de travail
|
||||
New Workspace… Nouvel espace de travail…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2492,6 +2492,8 @@ file-filter Templates Sablonok
|
||||
New View Új nézet
|
||||
New View… Új nézet…
|
||||
New Window Új ablak
|
||||
Next Document Következő dokumentum
|
||||
Previous Document Előző dokumentum
|
||||
New Without Dialog Új párbeszédablak nélkül
|
||||
New Workspace Új munkaterület
|
||||
New Workspace… Új munkaterület…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -578,6 +578,8 @@
|
||||
Saved View 25 Tampilan tersimpan 25
|
||||
Window Jendela
|
||||
New Window Jendela baru
|
||||
Next Document Dokumen berikutnya
|
||||
Previous Document Dokumen sebelumnya
|
||||
Cascade Bertingkat
|
||||
Tile Ubin
|
||||
Float in Window Mengambang di jendela
|
||||
|
||||
|
@@ -2073,6 +2073,8 @@ file-filter Templates Modelli
|
||||
New View Nuova vista
|
||||
New View… Nuova vista…
|
||||
New Window Nuova finestra
|
||||
Next Document Documento successivo
|
||||
Previous Document Documento precedente
|
||||
New Without Dialog Nuovo senza finestra di dialogo
|
||||
New Workspace Nuova area di lavoro
|
||||
New Workspace… Nuova area di lavoro…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -616,6 +616,8 @@ font-technology Variable バリアブル
|
||||
Saved View 25 保存した表示 25
|
||||
Window ウィンドウ
|
||||
New Window 新規ウィンドウ
|
||||
Next Document 次のドキュメント
|
||||
Previous Document 前のドキュメント
|
||||
Cascade 重ねて表示
|
||||
Tile 並べて表示
|
||||
Float in Window ウィンドウを分離
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -530,6 +530,8 @@
|
||||
Saved View 25 შენახული ხედი 25
|
||||
Window ფანჯარა
|
||||
New Window ახალი ფანჯარა
|
||||
Next Document შემდეგი დოკუმენტი
|
||||
Previous Document წინა დოკუმენტი
|
||||
Cascade კასკადად
|
||||
Tile ფილებად
|
||||
Float in Window ცალკე ფანჯარაში გამოტანა
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -614,6 +614,8 @@ font-technology Variable 가변
|
||||
Saved View 25 저장된 보기 25
|
||||
Window 윈도우
|
||||
New Window 새 창
|
||||
Next Document 다음 문서
|
||||
Previous Document 이전 문서
|
||||
Cascade 계단식 배열
|
||||
Tile 바둑판식 배열
|
||||
Float in Window 창에 플로팅
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -592,6 +592,8 @@
|
||||
Saved View 25 Opgeslagen weergave 25
|
||||
Window Venster
|
||||
New Window Nieuw venster
|
||||
Next Document Volgend document
|
||||
Previous Document Vorig document
|
||||
Cascade Trapsgewijs schikken
|
||||
Tile Naast elkaar schikken
|
||||
Float in Window In venster zweven
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -583,6 +583,8 @@
|
||||
Saved View 25 Zapisany widok 25
|
||||
Window Okno
|
||||
New Window Nowe okno
|
||||
Next Document Następny dokument
|
||||
Previous Document Poprzedni dokument
|
||||
Cascade Kaskadowo
|
||||
Tile Sąsiadująco
|
||||
Float in Window Pływające w oknie
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1653,6 +1653,8 @@
|
||||
New Symbol… Novo Símbolo…
|
||||
New View… Nova Visualização…
|
||||
New Window Nova Janela
|
||||
Next Document Próximo Documento
|
||||
Previous Document Documento Anterior
|
||||
New Without Dialog Novo sem Diálogo
|
||||
New Workspace Novo Espaço de Trabalho
|
||||
New Workspace… Novo Espaço de Trabalho…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2069,6 +2069,8 @@ file-filter Templates Шаблоны
|
||||
New View Новый вид
|
||||
New View… Новый вид…
|
||||
New Window Новое окно
|
||||
Next Document Следующий документ
|
||||
Previous Document Предыдущий документ
|
||||
New Without Dialog Создать без диалогового окна
|
||||
New Workspace Новая рабочая среда
|
||||
New Workspace… Новая рабочая среда…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1991,6 +1991,8 @@ font-technology Variable Variabla
|
||||
New View Ny vy
|
||||
New View… Ny vy…
|
||||
New Window Nytt fönster
|
||||
Next Document Nästa dokument
|
||||
Previous Document Föregående dokument
|
||||
New Without Dialog Ny utan dialogruta
|
||||
New Workspace Ny arbetslayout
|
||||
New Workspace… Ny arbetslayout…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -1871,6 +1871,8 @@ font-technology Variable Değişken
|
||||
New View Yeni Görünüm
|
||||
New View… Yeni Görünüm…
|
||||
New Window Yeni Pencere
|
||||
Next Document Sonraki Belge
|
||||
Previous Document Önceki Belge
|
||||
New Workspace Yeni Çalışma Alanı
|
||||
New Workspace… Yeni Çalışma Alanı…
|
||||
New {kind} Style… Yeni {kind} Stili…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -2065,6 +2065,8 @@ file-filter Templates Шаблони
|
||||
New View Новий вигляд
|
||||
New View… Новий вигляд…
|
||||
New Window Нове вікно
|
||||
Next Document Наступний документ
|
||||
Previous Document Попередній документ
|
||||
New Without Dialog Створити без діалогового вікна
|
||||
New Workspace Нове робоче середовище
|
||||
New Workspace… Нове робоче середовище…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 178 and column 5.
|
@@ -2300,6 +2300,8 @@ file-filter Templates Mẫu
|
||||
New View Chế độ xem mới
|
||||
New View… Chế độ xem mới…
|
||||
New Window Cửa sổ mới
|
||||
Next Document Tài liệu tiếp theo
|
||||
Previous Document Tài liệu trước
|
||||
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…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 200 and column 5.
|
@@ -1944,6 +1944,8 @@ file-filter Templates 模板
|
||||
New View 新建视图
|
||||
New View… 新建视图…
|
||||
New Window 新建窗口
|
||||
Next Document 下一个文档
|
||||
Previous Document 上一个文档
|
||||
New Without Dialog 无对话框新建
|
||||
New Workspace 新建工作区
|
||||
New Workspace… 新建工作区…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2869,6 +2869,8 @@ file-filter Templates 範本
|
||||
New View 新增檢視
|
||||
New View… 新增檢視…
|
||||
New Window 新增視窗
|
||||
Next Document 下一個文件
|
||||
Previous Document 上一個文件
|
||||
New Without Dialog 新增但不開啟對話方塊
|
||||
New Workspace 新增工作區
|
||||
New Workspace… 新增工作區…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -511,6 +511,8 @@ fn run_ui_part6(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<Result<
|
||||
None => Err("brightness must be dark|mediumDark|mediumLight|light".into()),
|
||||
},
|
||||
"window.newWindow" => Err("New Window isn't available yet: a document opens in one window".into()),
|
||||
"window.nextDocument" => crate::chrome::step_document(app, true),
|
||||
"window.previousDocument" => crate::chrome::step_document(app, false),
|
||||
"tool.select" => match s("tool") {
|
||||
Some(t) if vectorcraft_tools::tool_info(&t).is_some() => {
|
||||
app.select_tool(&t);
|
||||
|
||||
@@ -263,6 +263,7 @@ pub fn enabled(app: &VectorcraftApp, id: &str) -> bool {
|
||||
"ui.perspectivePlane" => app.session.active().is_some(),
|
||||
// Only one window per document so far: greyed out, as Window › Arrange's items are (#3724).
|
||||
"window.newWindow" => false,
|
||||
"window.nextDocument" | "window.previousDocument" => !app.session.documents().is_empty(),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,6 +518,18 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
|
||||
("window.workspace.rename", "Rename Workspace", "", "{name, to}"),
|
||||
("window.workspace.list", "List Workspaces", "", "{}"),
|
||||
("window.newWindow", "New Window", "", "{}"),
|
||||
(
|
||||
"window.nextDocument",
|
||||
"Next Document",
|
||||
"Cmd+F6",
|
||||
"{} make the open document after the current one in tab order the current one, as a click on its tab does (after the last document it goes to the first, and from the Home screen to the first); returns {index}",
|
||||
),
|
||||
(
|
||||
"window.previousDocument",
|
||||
"Previous Document",
|
||||
"Cmd+Shift+F6",
|
||||
"{} make the open document before the current one in tab order the current one, as a click on its tab does (before the first document it goes to the last, and from the Home screen to the last); returns {index}",
|
||||
),
|
||||
("tool.select", "Select Tool", "", "{tool: id} (see tools)"),
|
||||
(
|
||||
"tool.setOption",
|
||||
|
||||
@@ -3270,6 +3270,11 @@ 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.
|
||||
`window.nextDocument` (Cmd/Ctrl+F6) and `window.previousDocument` (Cmd/Ctrl+Shift+F6) make the next and the previous
|
||||
open document in tab order the current one, as a click on its tab does, and return `{index}`. After the last document
|
||||
comes the first, and before the first document comes the last. From the Home screen they go to the first and the last
|
||||
document. With no document open they fail with "no document open". `document.activate {index}` makes a given document
|
||||
the current one.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"file.new","params":{"preset":"A4","orientation":"landscape","artboards":4,"artboardLayout":{"columns":2},"bleed":9}}}
|
||||
|
||||
@@ -623,6 +623,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+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.*`).
|
||||
- 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.
|
||||
|
||||
Reference in New Issue
Block a user