mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 02:07:09 -06:00
Merge pull request #2843 from dotCooCoo/feat/history-clear-history
History: the panel menu clears the history
This commit is contained in:
@@ -75,6 +75,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
),
|
||||
cmd!("edit.undo", "Undo", ["Edit"], Some("Cmd+Z"), "{}", can_undo, undo),
|
||||
cmd!("edit.redo", "Redo", ["Edit"], Some("Cmd+Shift+Z"), "{}", can_redo, redo),
|
||||
cmd!(
|
||||
"edit.clearHistory",
|
||||
"Clear History",
|
||||
[],
|
||||
None,
|
||||
"{} remove every undo and redo step of the active document (the History panel menu's Clear History): the document stays as it is, and clearing is not an undo step → {cleared: the number of steps removed}",
|
||||
can_clear_history,
|
||||
clear_history
|
||||
),
|
||||
cmd!(
|
||||
"edit.undoGroup.begin",
|
||||
"Begin Undo Group",
|
||||
@@ -418,6 +427,19 @@ fn redo(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
Ok(json!({ "redone": label }))
|
||||
}
|
||||
|
||||
/// History panel › Clear History: removes the steps after the current state and the steps before
|
||||
/// it, and leaves the document as it is. Typing or a drag still in progress is first kept as a
|
||||
/// step, as Undo keeps it, so it is removed with the others and its change stays in the document.
|
||||
fn clear_history(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
settle_interaction(s)?;
|
||||
let st = s.doc_mut()?;
|
||||
let cleared = st.history.undo.len() + st.history.redo.len();
|
||||
st.history.undo.clear();
|
||||
st.history.redo.clear();
|
||||
st.revision += 1;
|
||||
Ok(json!({ "cleared": cleared }))
|
||||
}
|
||||
|
||||
/// `selection` for an undo (redo) step, sharing that of `like`, the step beside it, when the same.
|
||||
fn shared_selection(selection: vectorcraft_doc::Selection, like: Option<&crate::HistoryEntry>) -> Arc<vectorcraft_doc::Selection> {
|
||||
match like {
|
||||
|
||||
@@ -181,6 +181,10 @@ pub fn can_undo(s: &Session) -> std::result::Result<(), String> {
|
||||
pub fn can_redo(s: &Session) -> std::result::Result<(), String> {
|
||||
s.active().filter(|d| !d.history.redo.is_empty()).map(|_| ()).ok_or_else(|| "nothing to redo".into())
|
||||
}
|
||||
/// The active document has a step to undo or to redo (Clear History).
|
||||
pub fn can_clear_history(s: &Session) -> std::result::Result<(), String> {
|
||||
s.active().filter(|d| !d.history.undo.is_empty() || !d.history.redo.is_empty()).map(|_| ()).ok_or_else(|| "no history to clear".into())
|
||||
}
|
||||
pub fn has_clipboard(s: &Session) -> std::result::Result<(), String> {
|
||||
has_doc(s)?;
|
||||
if s.clipboard.is_empty() { Err("clipboard is empty".into()) } else { Ok(()) }
|
||||
|
||||
@@ -28,6 +28,61 @@ fn create_and_undo_redo() {
|
||||
assert!(s.execute("edit.redo", &json!({})).is_err());
|
||||
}
|
||||
|
||||
/// Clear History removes the steps to undo and the steps to redo. The document and the selection
|
||||
/// stay as they are, Undo and Redo are then disabled, and clearing is not a step itself.
|
||||
#[test]
|
||||
fn clear_history_removes_every_step_and_keeps_the_document() {
|
||||
let mut s = session();
|
||||
let a = rect(&mut s, 10.0, 10.0, 100.0, 50.0);
|
||||
let b = rect(&mut s, 200.0, 10.0, 100.0, 50.0);
|
||||
rect(&mut s, 400.0, 10.0, 100.0, 50.0);
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
let st = s.doc().unwrap();
|
||||
assert_eq!((st.history.undo.len(), st.history.redo.len()), (2, 1));
|
||||
let (doc, selection, dirty) = (st.doc.clone(), st.selection.clone(), st.is_dirty());
|
||||
assert_eq!(s.execute("edit.clearHistory", &json!({})).unwrap(), json!({"cleared": 3}));
|
||||
let st = s.doc().unwrap();
|
||||
assert_eq!((st.history.undo.len(), st.history.redo.len()), (0, 0));
|
||||
assert!(Arc::ptr_eq(&st.doc, &doc), "the document is the one from before clearing");
|
||||
assert_eq!((&st.selection, st.is_dirty()), (&selection, dirty));
|
||||
assert!(st.doc.node(a).is_some() && st.doc.node(b).is_some());
|
||||
for cmd in ["edit.undo", "edit.redo", "edit.clearHistory"] {
|
||||
assert!(matches!(s.execute(cmd, &json!({})), Err(EngineError::Disabled(..))), "{cmd}");
|
||||
}
|
||||
// A new edit is a step again: undoing it goes back to the document the history was cleared at.
|
||||
rect(&mut s, 600.0, 10.0, 100.0, 50.0);
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert!(Arc::ptr_eq(&s.doc().unwrap().doc, &doc));
|
||||
assert!(s.execute("edit.undo", &json!({})).is_err());
|
||||
}
|
||||
|
||||
/// Clear History is disabled without a document and in a document with no step to undo or redo.
|
||||
#[test]
|
||||
fn clear_history_needs_a_step_to_clear() {
|
||||
let mut s = Session::new();
|
||||
assert!(matches!(s.execute("edit.clearHistory", &json!({})), Err(EngineError::Disabled(..))), "no document");
|
||||
s.execute("file.new", &json!({})).unwrap();
|
||||
match s.execute("edit.clearHistory", &json!({})) {
|
||||
Err(EngineError::Disabled(_, why)) => assert_eq!(why, "no history to clear"),
|
||||
other => panic!("a new document: {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// A drag still in progress when the history is cleared ends, and its change stays in the document
|
||||
/// without a step to undo it.
|
||||
#[test]
|
||||
fn clear_history_keeps_a_drag_in_progress_in_the_document() {
|
||||
let mut s = session();
|
||||
let a = rect(&mut s, 10.0, 10.0, 100.0, 50.0);
|
||||
s.begin_interaction("Move").unwrap();
|
||||
s.preview("object.move", &json!({"dx": 30, "dy": 0})).unwrap();
|
||||
assert_eq!(s.execute("edit.clearHistory", &json!({})).unwrap(), json!({"cleared": 2}));
|
||||
assert!(!s.in_interaction());
|
||||
let st = s.doc().unwrap();
|
||||
assert_eq!(st.doc.node(a).unwrap().geometric_bounds().unwrap().x0, 40.0);
|
||||
assert!(st.history.undo.is_empty() && st.history.redo.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_and_disabled() {
|
||||
let mut s = Session::new();
|
||||
|
||||
@@ -6440,6 +6440,34 @@ mod tests {
|
||||
assert_eq!(plain(&app, id), "");
|
||||
}
|
||||
|
||||
/// Clear History waits while an IME composes, as Undo does: the marked text and the steps stay.
|
||||
#[test]
|
||||
fn clear_history_waits_while_the_ime_composes() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.session.prefs.placeholder_text = false;
|
||||
app.session.execute("file.new", &json!({"width": 400, "height": 300})).unwrap();
|
||||
app.session.execute("shape.rectangle", &json!({"x": 300, "y": 200, "width": 20, "height": 20})).unwrap();
|
||||
let ctx = egui::Context::default();
|
||||
typing_frame(&mut app, &ctx, vec![]);
|
||||
app.select_tool("type");
|
||||
let xf = Xf::new(app.canvas_rect.unwrap(), app.view().unwrap());
|
||||
let at = xf.to_screen(Point::new(100.0, 100.0));
|
||||
let click =
|
||||
|p: Pos2, pressed| egui::Event::PointerButton { pos: p, button: egui::PointerButton::Primary, pressed, modifiers: Default::default() };
|
||||
typing_frame(&mut app, &ctx, vec![egui::Event::PointerMoved(at), click(at, true)]);
|
||||
typing_frame(&mut app, &ctx, vec![click(at, false)]);
|
||||
let id = app.session.active().unwrap().selection.objects[0].0;
|
||||
typing_frame(&mut app, &ctx, vec![preedit("が", 1)]);
|
||||
assert!(app.session.tool_composing());
|
||||
assert!(!crate::menus::enabled(&app, "edit.clearHistory"));
|
||||
crate::menus::invoke(&mut app, "edit.clearHistory", json!({}));
|
||||
assert!(app.session.tool_composing(), "the composition goes on");
|
||||
assert!(!app.session.active().unwrap().history.undo.is_empty(), "the steps stay");
|
||||
typing_frame(&mut app, &ctx, vec![preedit("", 0), egui::Event::Ime(egui::ImeEvent::Commit("雅".into()))]);
|
||||
assert_eq!(plain(&app, id), "雅");
|
||||
assert!(crate::menus::enabled(&app, "edit.clearHistory"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clicking_away_mid_composition_keeps_the_text_and_interrupts_the_ime() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
|
||||
@@ -1323,6 +1323,7 @@
|
||||
History Options… Опции за историята…
|
||||
Step Backward Стъпка назад
|
||||
Step Forward Стъпка напред
|
||||
Clear History Изчистване на историята
|
||||
Set History Limit… Задаване на ограничение на историята…
|
||||
History States Състояния на историята
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -3966,6 +3967,7 @@ axis Both И двете
|
||||
@msg nothing to redo няма какво да се повтори
|
||||
@msg nothing to save: the document has no visible art няма нищо за запазване: документът няма видима графика
|
||||
@msg nothing to undo няма какво да се отмени
|
||||
@msg no history to clear няма история за изчистване
|
||||
@msg nothing to warp няма нищо за извиване
|
||||
@msg nothing to wrap няма нищо за обвиване
|
||||
@msg object {0} cannot have children обектът {0} не може да има дъщерни елементи
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1518,6 +1518,7 @@ lighting Light Světlo
|
||||
History Options… Možnosti historie…
|
||||
Step Backward Krok zpět
|
||||
Step Forward Krok vpřed
|
||||
Clear History Vymazat historii
|
||||
Set History Limit… Nastavit limit historie…
|
||||
Open a document to see its history. Otevřete dokument, abyste viděli jeho historii.
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4347,6 +4348,7 @@ imageTrace Outline Obrys
|
||||
@msg nothing to redo není co opakovat
|
||||
@msg nothing to save: the document has no visible art není co uložit: dokument nemá žádnou viditelnou kresbu
|
||||
@msg nothing to undo není co vrátit
|
||||
@msg no history to clear není žádná historie k vymazání
|
||||
@msg nothing to warp není co pokřivit
|
||||
@msg nothing to wrap není co obtékat
|
||||
@msg object {0} cannot have children objekt {0} nemůže mít potomky
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1439,6 +1439,7 @@ lighting Light Lys
|
||||
History Options… Indstillinger for historik…
|
||||
Step Backward Et trin tilbage
|
||||
Step Forward Et trin frem
|
||||
Clear History Ryd historik
|
||||
Set History Limit… Angiv historikgrænse…
|
||||
Open a document to see its history. Åbn et dokument for at se dets historik.
|
||||
Abutting Stødende
|
||||
@@ -4083,6 +4084,7 @@ imageTrace Outline Kontur
|
||||
@msg nothing to redo intet at gendanne
|
||||
@msg nothing to save: the document has no visible art intet at gemme: dokumentet har ingen synlig grafik
|
||||
@msg nothing to undo intet at fortryde
|
||||
@msg no history to clear ingen historik at rydde
|
||||
@msg nothing to warp intet at forvride
|
||||
@msg nothing to wrap intet at ombryde
|
||||
@msg object {0} cannot have children objektet {0} kan ikke have underobjekter
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1341,6 +1341,7 @@ file-filter Templates Vorlagen
|
||||
History Options… Protokolloptionen…
|
||||
Step Backward Schritt zurück
|
||||
Step Forward Schritt vorwärts
|
||||
Clear History Protokoll löschen
|
||||
Set History Limit… Protokollgrenze festlegen…
|
||||
History States Protokollschritte
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -3984,6 +3985,7 @@ theme Appearance Erscheinungsbild
|
||||
@msg nothing to redo nichts zu wiederholen
|
||||
@msg nothing to save: the document has no visible art nichts zu speichern: Das Dokument enthält keine sichtbare Grafik
|
||||
@msg nothing to undo nichts rückgängig zu machen
|
||||
@msg no history to clear kein Protokoll zu löschen
|
||||
@msg nothing to warp nichts zu verkrümmen
|
||||
@msg nothing to wrap nichts zu umfließen
|
||||
@msg object {0} cannot have children Objekt {0} kann keine untergeordneten Objekte haben
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1286,6 +1286,7 @@
|
||||
History Options… Επιλογές ιστορικού…
|
||||
Step Backward Ένα βήμα πίσω
|
||||
Step Forward Ένα βήμα εμπρός
|
||||
Clear History Εκκαθάριση ιστορικού
|
||||
Set History Limit… Ορισμός ορίου ιστορικού…
|
||||
History States Καταστάσεις ιστορικού
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4023,6 +4024,7 @@ theme Appearance Εμφάνιση
|
||||
@msg nothing to redo δεν υπάρχει τίποτα για επανάληψη
|
||||
@msg nothing to save: the document has no visible art δεν υπάρχει τίποτα για αποθήκευση: το έγγραφο δεν έχει ορατό σχέδιο
|
||||
@msg nothing to undo δεν υπάρχει τίποτα για αναίρεση
|
||||
@msg no history to clear δεν υπάρχει ιστορικό για εκκαθάριση
|
||||
@msg nothing to warp δεν υπάρχει τίποτα για στρέβλωση
|
||||
@msg nothing to wrap δεν υπάρχει τίποτα για αναδίπλωση
|
||||
@msg object {0} cannot have children το αντικείμενο {0} δεν μπορεί να έχει θυγατρικά στοιχεία
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2006 and column 19.
|
@@ -1349,6 +1349,7 @@
|
||||
History Options… Opciones de historial…
|
||||
Step Backward Paso atrás
|
||||
Step Forward Paso adelante
|
||||
Clear History Borrar historial
|
||||
Set History Limit… Definir límite de historial…
|
||||
History States Estados de historial
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4046,6 +4047,7 @@ axis Both Ambos
|
||||
@msg nothing to redo no hay nada que rehacer
|
||||
@msg nothing to save: the document has no visible art no hay nada que guardar: el documento no tiene ilustración visible
|
||||
@msg nothing to undo no hay nada que deshacer
|
||||
@msg no history to clear no hay historial que borrar
|
||||
@msg nothing to warp no hay nada que deformar
|
||||
@msg nothing to wrap no hay nada que envolver
|
||||
@msg object {0} cannot have children el objeto {0} no puede tener hijos
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1492,6 +1492,7 @@ lighting Light Valo
|
||||
History Options… Historian asetukset…
|
||||
Step Backward Askel taaksepäin
|
||||
Step Forward Askel eteenpäin
|
||||
Clear History Tyhjennä historia
|
||||
Set History Limit… Aseta historian raja…
|
||||
Open a document to see its history. Avaa asiakirja, niin näet sen historian.
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4270,6 +4271,7 @@ imageTrace Outline Ääriviiva
|
||||
@msg nothing to redo ei tehtävää uudelleen
|
||||
@msg nothing to save: the document has no visible art ei tallennettavaa: asiakirjassa ei ole näkyvää kuvitusta
|
||||
@msg nothing to undo ei kumottavaa
|
||||
@msg no history to clear ei tyhjennettävää historiaa
|
||||
@msg nothing to warp ei taivutettavaa
|
||||
@msg nothing to wrap ei rivitettävää
|
||||
@msg object {0} cannot have children objektilla {0} ei voi olla alikohteita
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1348,6 +1348,7 @@
|
||||
History Options… Options d’historique…
|
||||
Step Backward Pas en arrière
|
||||
Step Forward Pas en avant
|
||||
Clear History Effacer l’historique
|
||||
Set History Limit… Définir la limite de l’historique…
|
||||
History States États de l’historique
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4043,6 +4044,7 @@ axis Both Les deux
|
||||
@msg nothing to redo rien à rétablir
|
||||
@msg nothing to save: the document has no visible art rien à enregistrer : le document n’a aucune illustration visible
|
||||
@msg nothing to undo rien à annuler
|
||||
@msg no history to clear aucun historique à effacer
|
||||
@msg nothing to warp rien à déformer
|
||||
@msg nothing to wrap rien à envelopper
|
||||
@msg object {0} cannot have children l’objet {0} ne peut pas avoir d’enfants
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1722,6 +1722,7 @@ file-filter Templates Sablonok
|
||||
History Options… Előzmények beállításai…
|
||||
Step Backward Lépés vissza
|
||||
Step Forward Lépés előre
|
||||
Clear History Előzmények törlése
|
||||
Set History Limit… Előzménykorlát beállítása…
|
||||
History States Előzmények lépésszáma
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4693,6 +4694,7 @@ imageTrace Outline Körvonal
|
||||
@msg nothing to redo nincs mit újra végrehajtani
|
||||
@msg nothing to save: the document has no visible art nincs mit menteni: a dokumentumban nincs látható grafika
|
||||
@msg nothing to undo nincs mit visszavonni
|
||||
@msg no history to clear nincs törölhető előzmény
|
||||
@msg nothing to warp nincs mit torzítani
|
||||
@msg nothing to wrap nincs mit körbefuttatni
|
||||
@msg object ids are non-negative integers, not {v} az objektumazonosító nemnegatív egész szám, ez nem az: {v}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1439,6 +1439,7 @@ lighting Light Cahaya
|
||||
History Options… Opsi riwayat…
|
||||
Step Backward Mundur satu langkah
|
||||
Step Forward Maju satu langkah
|
||||
Clear History Hapus riwayat
|
||||
Set History Limit… Atur batas riwayat…
|
||||
Open a document to see its history. Buka dokumen untuk melihat riwayatnya.
|
||||
Abutting Bersinggungan
|
||||
@@ -4083,6 +4084,7 @@ imageTrace Outline Kontur
|
||||
@msg nothing to redo tidak ada yang dapat dipulihkan
|
||||
@msg nothing to save: the document has no visible art tidak ada yang dapat disimpan: dokumen tidak memiliki karya seni yang terlihat
|
||||
@msg nothing to undo tidak ada yang dapat diurungkan
|
||||
@msg no history to clear tidak ada riwayat yang dapat dihapus
|
||||
@msg nothing to warp tidak ada yang dapat diubah bentuknya
|
||||
@msg nothing to wrap tidak ada yang dapat dibungkus
|
||||
@msg object {0} cannot have children objek {0} tidak dapat memiliki anak
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3768 and column 19.
|
@@ -1358,6 +1358,7 @@ file-filter Templates Modelli
|
||||
History Options… Opzioni cronologia…
|
||||
Step Backward Passo indietro
|
||||
Step Forward Passo avanti
|
||||
Clear History Cancella cronologia
|
||||
Set History Limit… Imposta limite cronologia…
|
||||
History States Stati cronologia
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4085,6 +4086,7 @@ axis Both Entrambi
|
||||
@msg nothing to redo niente da ripetere
|
||||
@msg nothing to save: the document has no visible art niente da salvare: il documento non ha grafica visibile
|
||||
@msg nothing to undo niente da annullare
|
||||
@msg no history to clear nessuna cronologia da cancellare
|
||||
@msg nothing to warp niente da alterare
|
||||
@msg nothing to wrap niente da avvolgere
|
||||
@msg object {0} cannot have children l'oggetto {0} non può avere elementi figli
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1603,6 +1603,7 @@
|
||||
History Options… ヒストリーオプション…
|
||||
Step Backward 一段階戻る
|
||||
Step Forward 一段階進む
|
||||
Clear History ヒストリーを消去
|
||||
Set History Limit… ヒストリーの上限を設定…
|
||||
History States ヒストリー数
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -3885,6 +3886,7 @@ swatch Bright Violet ビビッドバイオレット
|
||||
@msg object {id} is not a selected top-level object オブジェクト {id} は選択されている最上位のオブジェクトではありません
|
||||
@msg nothing to redo やり直す操作がありません
|
||||
@msg nothing to undo 取り消す操作がありません
|
||||
@msg no history to clear 消去するヒストリーがありません
|
||||
@msg Expand Appearance: the selection has a basic appearance アピアランスを分割: 選択範囲は基本アピアランスです
|
||||
@msg select (or target) objects whose appearance isn't basic 基本アピアランスではないオブジェクトを選択するか、ターゲットに指定してください
|
||||
@msg {C}: no effect at index {from} {C}: インデックス {from} に効果がありません
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1598,6 +1598,7 @@
|
||||
History Options… 히스토리 옵션…
|
||||
Step Backward 한 단계 뒤로
|
||||
Step Forward 한 단계 앞으로
|
||||
Clear History 히스토리 지우기
|
||||
Set History Limit… 히스토리 한도 설정…
|
||||
History States 히스토리 상태
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -3817,6 +3818,7 @@ theme Appearance 외관
|
||||
@msg object {id} is not a selected top-level object 개체 {id}은(는) 선택된 최상위 개체가 아닙니다
|
||||
@msg nothing to redo 다시 실행할 항목이 없습니다
|
||||
@msg nothing to undo 실행 취소할 항목이 없습니다
|
||||
@msg no history to clear 지울 히스토리가 없습니다
|
||||
@msg Expand Appearance: the selection has a basic appearance 모양새 확장: 선택 항목은 기본 모양새입니다
|
||||
@msg select (or target) objects whose appearance isn't basic 모양새가 기본이 아닌 개체를 선택(또는 대상 지정)하세요
|
||||
@msg {C}: no effect at index {from} {C}: 인덱스 {from}에 효과가 없습니다
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1453,6 +1453,7 @@ lighting Light Licht
|
||||
History Options… Historieopties…
|
||||
Step Backward Stap terug
|
||||
Step Forward Stap vooruit
|
||||
Clear History Historie wissen
|
||||
Set History Limit… Historielimiet instellen…
|
||||
Open a document to see its history. Open een document om de historie te zien.
|
||||
Abutting Aaneengesloten
|
||||
@@ -4097,6 +4098,7 @@ imageTrace Outline Contour
|
||||
@msg nothing to redo niets om opnieuw uit te voeren
|
||||
@msg nothing to save: the document has no visible art niets om op te slaan: het document heeft geen zichtbare illustratie
|
||||
@msg nothing to undo niets om ongedaan te maken
|
||||
@msg no history to clear geen historie om te wissen
|
||||
@msg nothing to warp niets om te buigen
|
||||
@msg nothing to wrap niets om te laten omlopen
|
||||
@msg object {0} cannot have children object {0} kan geen onderliggende objecten hebben
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1432,6 +1432,7 @@ lighting Light Światło
|
||||
History Options… Opcje historii…
|
||||
Step Backward Krok wstecz
|
||||
Step Forward Krok naprzód
|
||||
Clear History Wyczyść historię
|
||||
Set History Limit… Ustaw limit historii…
|
||||
Open a document to see its history. Otwórz dokument, aby zobaczyć jego historię.
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4171,6 +4172,7 @@ imageTrace Outline Kontur
|
||||
@msg nothing to redo nie ma czego ponowić
|
||||
@msg nothing to save: the document has no visible art nie ma czego zapisać: dokument nie ma widocznej kompozycji
|
||||
@msg nothing to undo nie ma czego cofnąć
|
||||
@msg no history to clear brak historii do wyczyszczenia
|
||||
@msg nothing to warp nie ma czego wypaczyć
|
||||
@msg nothing to wrap nie ma czego oblewać
|
||||
@msg object {0} cannot have children obiekt {0} nie może mieć elementów podrzędnych
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1163,6 +1163,7 @@
|
||||
History Options… Opções do Histórico…
|
||||
Step Backward Voltar um Passo
|
||||
Step Forward Avançar um Passo
|
||||
Clear History Limpar Histórico
|
||||
Set History Limit… Definir Limite do Histórico…
|
||||
History States Estados do Histórico
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -3628,6 +3629,7 @@ axis Both Ambos
|
||||
@msg nothing to redo nada para refazer
|
||||
@msg nothing to save: the document has no visible art nada para salvar: o documento não tem arte visível
|
||||
@msg nothing to undo nada para desfazer
|
||||
@msg no history to clear nenhum histórico para limpar
|
||||
@msg nothing to warp nada para deformar
|
||||
@msg nothing to wrap nada para envolver
|
||||
@msg object {0} cannot have children o objeto {0} não pode ter filhos
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -1356,6 +1356,7 @@ file-filter Templates Шаблоны
|
||||
History Options… Параметры истории…
|
||||
Step Backward Шаг назад
|
||||
Step Forward Шаг вперёд
|
||||
Clear History Очистить историю
|
||||
Set History Limit… Задать предел истории…
|
||||
History States Состояния истории
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4081,6 +4082,7 @@ axis Both Оба
|
||||
@msg nothing to redo нечего повторять
|
||||
@msg nothing to save: the document has no visible art нечего сохранять: в документе нет видимого рисунка
|
||||
@msg nothing to undo нечего отменять
|
||||
@msg no history to clear нет истории для очистки
|
||||
@msg nothing to warp нечего деформировать
|
||||
@msg nothing to wrap нечего обтекать
|
||||
@msg object {0} cannot have children объект {0} не может иметь потомков
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1325,6 +1325,7 @@
|
||||
History Options… Historikalternativ…
|
||||
Step Backward Stega bakåt
|
||||
Step Forward Stega framåt
|
||||
Clear History Rensa historik
|
||||
Set History Limit… Ange historikgräns…
|
||||
History States Historiktillstånd
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -3971,6 +3972,7 @@ axis Both Båda
|
||||
@msg nothing to redo inget att göra om
|
||||
@msg nothing to save: the document has no visible art inget att spara: dokumentet har ingen synlig grafik
|
||||
@msg nothing to undo inget att ångra
|
||||
@msg no history to clear ingen historik att rensa
|
||||
@msg nothing to warp inget att böja
|
||||
@msg nothing to wrap inget att radbryta
|
||||
@msg object {0} cannot have children objekt {0} kan inte ha underordnade objekt
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -1352,6 +1352,7 @@ file-filter Templates Шаблони
|
||||
History Options… Параметри історії…
|
||||
Step Backward Крок назад
|
||||
Step Forward Крок вперед
|
||||
Clear History Очистити історію
|
||||
Set History Limit… Задати межу історії…
|
||||
History States Стан історії
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4069,6 +4070,7 @@ axis Both Обидві
|
||||
@msg nothing to redo нічого повторювати
|
||||
@msg nothing to save: the document has no visible art нічого зберігати: у документі немає видимого малюнка
|
||||
@msg nothing to undo нічого скасовувати
|
||||
@msg no history to clear немає історії для очищення
|
||||
@msg nothing to warp нічого деформувати
|
||||
@msg nothing to wrap нічого обтікати
|
||||
@msg object {0} cannot have children об’єкт {0} не може мати нащадків
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 725 and column 40.
|
@@ -1551,6 +1551,7 @@ file-filter Templates Mẫu
|
||||
History Options… Tùy chọn lịch sử…
|
||||
Step Backward Lùi một bước
|
||||
Step Forward Tiến một bước
|
||||
Clear History Xóa lịch sử
|
||||
Set History Limit… Đặt giới hạn lịch sử…
|
||||
History States Trạng thái lịch sử
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -4342,6 +4343,7 @@ theme Appearance Giao diện
|
||||
@msg nothing to redo không có gì để làm lại
|
||||
@msg nothing to save: the document has no visible art không có gì để lưu: tài liệu không có tác phẩm hiển thị
|
||||
@msg nothing to undo không có gì để hoàn tác
|
||||
@msg no history to clear không có lịch sử để xóa
|
||||
@msg nothing to warp không có gì để biến dạng
|
||||
@msg nothing to wrap không có gì để bọc
|
||||
@msg object ids are non-negative integers, not {v} id đối tượng là số nguyên không âm, không phải {v}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3948 and column 10.
|
@@ -1300,6 +1300,7 @@ file-filter Templates 模板
|
||||
History Options… 历史记录选项…
|
||||
Step Backward 后退一步
|
||||
Step Forward 前进一步
|
||||
Clear History 清除历史记录
|
||||
Set History Limit… 设置历史记录上限…
|
||||
History States 历史记录步数
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
@@ -3638,6 +3639,7 @@ imageTrace Outline 轮廓
|
||||
@msg object {id} is not a selected top-level object 对象 {id} 不是选中的顶层对象
|
||||
@msg nothing to redo 没有可重做的操作
|
||||
@msg nothing to undo 没有可撤销的操作
|
||||
@msg no history to clear 没有可清除的历史记录
|
||||
@msg Expand Appearance: the selection has a basic appearance 扩展外观:所选对象只有基本外观
|
||||
@msg select (or target) objects whose appearance isn't basic 请选择 (或定位) 外观不是基本外观的对象
|
||||
@msg {C}: no effect at index {from} {C}:索引 {from} 处没有效果
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1330,6 +1330,7 @@ file-filter Templates 範本
|
||||
History Options… 步驟記錄選項…
|
||||
Step Backward 後退一步
|
||||
Step Forward 前進一步
|
||||
Clear History 清除步驟記錄
|
||||
Set History Limit… 設定步驟記錄上限…
|
||||
History States 步驟記錄狀態
|
||||
# History panel: the names of undo steps (`every_undo_label_is_translated`).
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2194,12 +2194,14 @@ pub fn shortcut_of(id: &str) -> Option<&'static str> {
|
||||
/// Commands that would act on the text being typed, held back while an IME composes in the Type
|
||||
/// tool (its marked text isn't committed yet): Undo/Redo — the native menu takes ⌘Z ahead of the
|
||||
/// IME —, the clipboard and the selection.
|
||||
/// Clear History also waits: it ends the typing session as Undo does.
|
||||
pub(crate) fn waits_for_ime(app: &VectorcraftApp, id: &str) -> bool {
|
||||
app.session.tool_composing()
|
||||
&& (matches!(
|
||||
id,
|
||||
"edit.undo" | "edit.redo" | "edit.cut" | "edit.copy" | "edit.clear" | "edit.duplicate" | "select.all" | "select.none" | "select.inverse"
|
||||
) || id.starts_with("edit.paste"))
|
||||
) || id == "edit.clearHistory"
|
||||
|| id.starts_with("edit.paste"))
|
||||
}
|
||||
|
||||
pub fn enabled(app: &VectorcraftApp, id: &str) -> bool {
|
||||
|
||||
@@ -96,6 +96,9 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
}
|
||||
}
|
||||
ui.separator();
|
||||
if menu_item(ui, tl!("Clear History"), crate::menus::enabled(app, "edit.clearHistory"), false) {
|
||||
crate::menus::invoke(app, "edit.clearHistory", json!({}));
|
||||
}
|
||||
if menu_item(ui, tl!("Set History Limit…"), true, false) {
|
||||
crate::menus::invoke(app, "edit.preferences", json!({ "category": "Performance" }));
|
||||
}
|
||||
@@ -253,6 +256,46 @@ mod tests {
|
||||
assert_eq!(depth(&app), (0, 1));
|
||||
}
|
||||
|
||||
/// Returns whether the panel menu's item labeled `label` is disabled.
|
||||
fn disabled(app: &mut VectorcraftApp, label: &str) -> bool {
|
||||
let tree = crate::widgets::accessibility_tests::tree(|ui| menu(app, ui));
|
||||
tree.iter().find(|n| n.label().map(str::trim) == Some(label)).unwrap_or_else(|| panic!("no `{label}`")).is_disabled()
|
||||
}
|
||||
|
||||
/// The panel menu's Clear History removes the steps to undo and to redo, and the document stays
|
||||
/// as it is. Step Backward and Step Forward are then disabled.
|
||||
#[test]
|
||||
fn the_panel_menu_clears_the_history() {
|
||||
let mut app = app_with_two_rectangles();
|
||||
click(&mut app, "Step Backward");
|
||||
assert_eq!(depth(&app), (1, 1));
|
||||
let doc = app.session.active().unwrap().doc.clone();
|
||||
click(&mut app, "Clear History");
|
||||
assert_eq!(depth(&app), (0, 0));
|
||||
assert!(std::sync::Arc::ptr_eq(&app.session.active().unwrap().doc, &doc), "the document stays as it is");
|
||||
assert_eq!((disabled(&mut app, "Step Backward"), disabled(&mut app, "Step Forward")), (true, true));
|
||||
}
|
||||
|
||||
/// Clear History is disabled with no document and with no step to undo or redo, and a click on it
|
||||
/// then changes nothing.
|
||||
#[test]
|
||||
fn clear_history_is_disabled_with_no_step_to_clear() {
|
||||
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
|
||||
assert!(disabled(&mut app, "Clear History"), "no document");
|
||||
app.session.execute("file.new", &json!({"width": 200, "height": 150})).unwrap();
|
||||
assert!(disabled(&mut app, "Clear History"), "a new document");
|
||||
app.session.execute("shape.rectangle", &json!({"x": 10, "y": 10, "width": 20, "height": 20})).unwrap();
|
||||
assert!(!disabled(&mut app, "Clear History"), "one step to undo");
|
||||
click(&mut app, "Step Backward");
|
||||
assert!(!disabled(&mut app, "Clear History"), "one step to redo");
|
||||
click(&mut app, "Clear History");
|
||||
assert_eq!(depth(&app), (0, 0));
|
||||
assert!(disabled(&mut app, "Clear History"), "the history cleared");
|
||||
let revision = app.session.active().unwrap().revision;
|
||||
click(&mut app, "Clear History");
|
||||
assert_eq!(app.session.active().unwrap().revision, revision, "a click on the disabled item changes nothing");
|
||||
}
|
||||
|
||||
/// Set History Limit… opens Preferences at Performance, the page with History States.
|
||||
#[test]
|
||||
fn set_history_limit_opens_the_history_states_preference() {
|
||||
|
||||
+1
-1
@@ -353,7 +353,7 @@ objects' fills or strokes differ (`fillMixed` / `strokeMixed`, drawn as a "?" pr
|
||||
| `transform` | `{ids?, dx?, dy?, rotate?, scale?, scaleX?, scaleY?, reflect?, shear?, origin?, copy?}` | Runs move, rotate, scale, reflect, shear in that order. With `copy`, the first step duplicates. |
|
||||
| `create_graph` | `{type?, x, y, width, height, csv? \| series?, categories?, rows?}` | The nine Illustrator graph types: column, stacked column, bar, stacked bar, line, area, scatter, pie and radar. An empty CSV cell or a `null` in `rows` is a blank value; a number in straight quotes is a label. Edit later with `graph.setData` / `graph.setType` via `run_command`. `graph.column {design, columnType: vertical\|uniform\|repeating\|sliding, each, fractions: chop\|scale}` draws the columns or bars of the series picked with Group Selection (or `seriesIndexes`, or all of them) with a graph design saved by `graph.design`; with no `design` it returns the series' current design and options. |
|
||||
| `text_wrap` | `{ids?, offset?, invert?, release?}` | Area type below the objects (same layer) flows around them. |
|
||||
| `undo` / `redo` | `{}` | Many calls that change nothing record no undo step, for example `object.align` with nothing to move, `object.move` by 0 without `copy` and `object.showAll` with nothing hidden. `undo` (`edit.undo`) after such a call undoes the step before it. `inspect_document` lists the undo steps as `history`. |
|
||||
| `undo` / `redo` | `{}` | Many calls that change nothing record no undo step, for example `object.align` with nothing to move, `object.move` by 0 without `copy` and `object.showAll` with nothing hidden. `undo` (`edit.undo`) after such a call undoes the step before it. `inspect_document` lists the undo steps as `history`. `run_command` with `edit.clearHistory` removes every undo and redo step of the active document and returns `{cleared}`, the number of steps removed; the document stays as it is, and the command records no undo step. |
|
||||
|
||||
For example, create editable Japanese area type with the engine's vertical writing mode:
|
||||
|
||||
|
||||
@@ -467,7 +467,8 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- Localised UI: menus (in-window and native), panels, dialogs, toolbar and Preferences read from per-language catalogs (`crates/ui-egui/src/i18n`, see `docs/development.md`); Traditional Chinese (Taiwan), Simplified Chinese (mainland), Japanese, Korean, Vietnamese, German, Spanish, French, Italian, Polish, Brazilian Portuguese, Russian and Ukrainian ship complete, and Czech covers every menu label (and more), with system-locale detection on macOS, Windows, Linux and the web (the browser's languages, or `?lang=`), a Language preference and, on macOS, a VectorCraft ▸ Language menu. Names are never translated (fonts and their styles, layers, artboards, saved presets, user libraries, custom workspaces, recent files, plug-ins).
|
||||
- Edit › Undo and Edit › Redo, in the in-window and native menus, name the step in the interface language as the History panel lists it (`panels::history::step_name`), so when the catalog has no plain row for a step named after an effect, such as Feather, the menu shows the translation of the effect's menu row without its ellipsis (`undo_and_redo_name_the_step_as_the_history_panel_does`).
|
||||
- The History panel translates the undo step names the engine, the tools and the shell write as literals: each has a row in every complete catalog (`every_undo_label_is_translated`), and a step whose catalog row exists only with an ellipsis (such as an effect's menu name) shows that row without the ellipsis.
|
||||
- The History panel menu has Step Backward and Step Forward, which run Edit › Undo and Edit › Redo and are disabled when there is no step to undo or redo, and Set History Limit…, which opens Preferences at Performance, where History States is set. Not done: Clear History and a new document from the selected state.
|
||||
- The History panel menu has Step Backward and Step Forward, which run Edit › Undo and Edit › Redo and are disabled when there is no step to undo or redo, and Set History Limit…, which opens Preferences at Performance, where History States is set. Not done: a new document from the selected state.
|
||||
- The History panel menu's Clear History (`edit.clearHistory`) removes every step to undo and to redo and leaves the document as it is; it is not an undo step itself, and it is disabled when there is no step to clear.
|
||||
- Native macOS menu bar, vector tool cursors, a ⌘K command palette, middle-button panning with any tool. Native menus explicitly end tracking on command selection, outside window presses and Escape; menu updates wait until tracking ends, and a dismissing press never starts a canvas gesture (M14.8).
|
||||
- The errors of the blend spine commands (Move Spine Point, Reshape Spine Segment, Add Spine Point and Delete Spine Point) show in the status bar in the interface language: each has a row in every catalog that translates all status and error messages and in Bulgarian (`blend_spine_param_errors_are_translated`).
|
||||
- The macOS menu bar is built from the in-window menus (one model, `native_menu`) and laid out as a Mac app's: the VectorCraft menu holds About, Settings ▸ (each Preferences page, General… ⌘K), Language ▸, Appearance ▸ (UI brightness), Services, Hide VectorCraft ⌃⌘H (⌘H stays Hide Edges), Hide Others, Show All and Quit; Window gains Minimize ⌃⌘M, Zoom and Bring All to Front, and Help the system's search field. Its key equivalents go back to egui as key presses, so user shortcuts, focused text fields and the Type tool's input method behave as in the window, and nothing fires twice; enabled, check marks and labels update in place. `--in-window-menus` or `VECTORCRAFT_IN_WINDOW_MENUS=1` keeps the menus in the window; `ui.inspect` reports `nativeMenuBar`.
|
||||
|
||||
Reference in New Issue
Block a user