Actions: New Action asks for the action's name, set, function key and color

Squashed from #5270 onto main.
This commit is contained in:
dotCooCoo
2026-11-03 20:27:02 +07:00
committed by bflatastic
parent 4db6e7b448
commit 40ed074cae
41 changed files with 1558 additions and 84 deletions
+1
View File
@@ -350,6 +350,7 @@ impl VectorcraftApp {
}
crate::keymap::note_os(ctx);
shortcut_editor::sync(&self.ui);
crate::panels::actions::sync_function_keys(&self.ui);
prefs_dialog::apply_runtime(self, ctx);
// The OS title bar (and the taskbar / Alt-Tab entry) follows the active file; with the
// system title bar this is where the document name lives, as the in-app mark is hidden.
+2
View File
@@ -8,6 +8,7 @@
mod about;
pub mod action_batch;
pub mod action_new;
pub mod action_set_options;
pub mod artboard_options;
pub mod blend_options;
@@ -361,6 +362,7 @@ registry! {
Package: [package::KIND] => package::SPEC,
ActionBatch: [action_batch::KIND] => action_batch::SPEC,
ActionSetOptions: [action_set_options::KIND] => action_set_options::SPEC,
ActionNew: [action_new::KIND] => action_new::SPEC,
SliceOptions: [slices::OPTIONS] => slices::OPTIONS_SPEC,
DivideSlices: [slices::DIVIDE] => slices::DIVIDE_SPEC,
EpsOptions: [eps_options::KIND] => eps_options::SPEC,
+120
View File
@@ -0,0 +1,120 @@
//! Actions panel › Create New Action (and ≡ › New Action…): the name, set, function key and color
//! of a new action. Record adds the action and starts recording into it (`ui.action.new`).
//!
//! Fields: `set` (the index of the set the action goes into), `name`, `key` (0 for none, 1 to 15
//! for F1 to F15), `cmd` (Ctrl, Command on macOS), `shift`, `color` (a value of
//! [`crate::panels::actions::COLORS`], `""` for none). An invalid set or function key is an error:
//! Record then adds nothing and the dialog stays open.
use serde_json::{Value, json};
use super::DialogSpec;
use crate::panels::actions::{COLORS, FUNCTION_KEYS, FunctionKey};
use crate::state::Dialog;
use crate::{VectorcraftApp, widgets};
/// The dialog kind of New Action.
pub const KIND: &str = "actionNew";
/// The width of the label column.
const LABEL_W: f32 = 90.0;
pub(super) const SPEC: DialogSpec = DialogSpec {
heading: |_| tl!("New Action").into(),
body,
confirm,
ok: Some("Record"),
ok_enabled: Some(|_, d| !d.str("name").trim().is_empty()),
min_width: 340.0,
..DialogSpec::FORM
};
/// Whether New Action can open: there is a set to put the action in and nothing is recording.
pub fn can_open(app: &VectorcraftApp) -> bool {
!app.ui.action_sets.is_empty() && app.ui.recording.is_none()
}
/// Opens New Action for the current set, else the first set, named "Action N" with the first
/// number from the set's action count plus one that no action of the set uses, with no function
/// key and no color.
pub fn open(app: &mut VectorcraftApp) -> Result<(), String> {
if app.ui.recording.is_some() {
return Err("an action is already recording".into());
}
let len = app.ui.action_sets.len();
let set = app.ui.action_set.filter(|&s| s < len).unwrap_or(0);
let Some(s) = app.ui.action_sets.get(set) else { return Err("no such action set".into()) };
let taken = |n: usize| s.actions.iter().any(|a| a.name == format!("Action {n}"));
let n = (s.actions.len() + 1..).find(|&n| !taken(n)).unwrap_or(1);
let fields = json!({"set": set, "name": format!("Action {n}"), "key": 0, "cmd": false, "shift": false, "color": ""});
app.ui.dialog = Some(Dialog::new(KIND, fields));
Ok(())
}
fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
widgets::label_row(ui, "Name:", LABEL_W, |ui| {
super::form::text(ui, d, "name", 200.0);
});
let names: Vec<&str> = app.ui.action_sets.iter().map(|s| s.name.as_str()).collect();
let set = d.fields.get("set").and_then(Value::as_u64).and_then(|i| usize::try_from(i).ok());
let shown = set.and_then(|s| names.get(s)).copied().unwrap_or_default();
widgets::label_row(ui, "Action Set:", LABEL_W, |ui| {
if let Some(i) = widgets::dropdown_names(ui, "action-new-set", shown, &names, 200.0) {
d.fields.insert("set".into(), json!(i));
}
});
key_and_color(ui, d);
false
}
/// The Function Key and Color rows of New Action and Action Options show errors for invalid keys.
pub(super) fn key_and_color(ui: &mut egui::Ui, d: &mut Dialog) {
let key = d.fields.get("key").and_then(Value::as_u64).unwrap_or(0);
let none = tl!("None");
let keys: Vec<String> = std::iter::once(none.to_string()).chain((1..=FUNCTION_KEYS).map(|n| format!("F{n}"))).collect();
let labels: Vec<&str> = keys.iter().map(String::as_str).collect();
let shown = usize::try_from(key).ok().and_then(|k| labels.get(k)).copied().unwrap_or(none);
let modifier = if crate::keymap::platform() == craft_keymap::Platform::Mac { "⌘" } else { "Ctrl" };
widgets::label_row(ui, "Function Key:", LABEL_W, |ui| {
if let Some(i) = widgets::dropdown_names(ui, "action-key", shown, &labels, 70.0) {
d.fields.insert("key".into(), json!(i));
}
super::form::check(ui, d, "cmd", modifier);
super::form::check(ui, d, "shift", "Shift");
});
let picked = FunctionKey::from_params(&json!({"key": key, "cmd": d.bool("cmd"), "shift": d.bool("shift")}));
if let Ok(Some(k)) = picked
&& let Some(message) = crate::panels::actions::key_error(k)
{
widgets::label_row(ui, "", LABEL_W, |ui| {
ui.label(crate::i18n::msg(&message));
});
}
let colors: Vec<(&str, &str)> = std::iter::once(("", "None")).chain(COLORS).collect();
super::form::choice(ui, d, "color", "Color:", (LABEL_W, 120.0), &colors);
}
/// The function key and color params the dialog's fields give, as `ui.action.new` and
/// `ui.action.options` take them.
pub(super) fn key_and_color_params(d: &Dialog) -> Value {
json!({
"key": d.fields.get("key").and_then(Value::as_u64).unwrap_or(0),
"cmd": d.bool("cmd"),
"shift": d.bool("shift"),
"color": d.str("color"),
})
}
fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
let name = d.str("name").trim().to_string();
// Record is disabled without a name; `ui.dialog.confirm` keeps the dialog open the same way.
if name.is_empty() {
return Ok(Value::Null);
}
let mut p = key_and_color_params(d);
p["set"] = d.fields.get("set").cloned().unwrap_or(Value::Null);
p["name"] = json!(name);
app.run(crate::panels::actions::NEW_ACTION, p)?;
app.ui.dialog = None;
Ok(Value::Null)
}
@@ -2,10 +2,12 @@
//! the name of a new action set, of the current one, or of the selected action.
//!
//! Fields: `set` (the index of the set renamed, or of the action's set; none for a new set),
//! `action` (the index of the action renamed, in `set`; none for a set) and `name`. OK adds the set
//! and makes it the current one, renames the set, or renames the action (`ui.action.rename`). A
//! `set` or `action` field that is not the index of a set or action is an error, OK then changes
//! no set or action, and the dialog stays open.
//! `action` (the index of the action renamed, in `set`; none for a set) and `name`. Action Options
//! also holds the action's function key and color, as New Action does (`key`, `cmd`, `shift`,
//! `color`, see [`super::action_new`]). OK adds the set and makes it the current
//! one, renames the set, or changes the action's name, function key and color
//! (`ui.action.options`). An invalid `set`, `action` or function key is an error. OK then changes no set or
//! action, and the dialog stays open.
use serde_json::{Value, json};
@@ -43,17 +45,26 @@ pub fn open(app: &mut VectorcraftApp, set: usize) {
}
}
/// Open Action Options for the action at `action` in set `set`, if there is one.
/// Open Action Options for the action at `action` in set `set`, if there is one, with its name,
/// function key and color.
pub fn open_action(app: &mut VectorcraftApp, set: usize, action: usize) {
if let Some(a) = app.ui.action_sets.get(set).and_then(|s| s.actions.get(action)) {
app.ui.dialog = Some(Dialog::new(KIND, json!({"set": set, "action": action, "name": a.name})));
let (key, cmd, shift) = a.key.map_or((0, false, false), |k| (k.key, k.cmd, k.shift));
let color = a.color.clone().unwrap_or_default();
let fields = json!({"set": set, "action": action, "name": a.name, "key": key, "cmd": cmd, "shift": shift, "color": color});
app.ui.dialog = Some(Dialog::new(KIND, fields));
}
}
fn body(_: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
widgets::label_row(ui, "Name:", 50.0, |ui| {
fn body(_app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
// Action Options lines its rows up with the Function Key and Color rows.
let action = d.fields.contains_key("action") && d.fields.contains_key("key");
widgets::label_row(ui, "Name:", if action { 90.0 } else { 50.0 }, |ui| {
super::form::text(ui, d, "name", 200.0);
});
if action {
super::action_new::key_and_color(ui, d);
}
false
}
@@ -65,7 +76,12 @@ fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
}
// The fields the dialog holds choose what OK does, as they choose its heading.
if d.fields.contains_key("action") {
app.run(crate::panels::actions::RENAME_ACTION, json!({"set": d.fields.get("set"), "action": d.fields.get("action"), "name": name}))?;
// A dialog without the key fields (made by `ui.dialog.set`) keeps the key and color.
let mut p = if d.fields.contains_key("key") { super::action_new::key_and_color_params(d) } else { json!({}) };
p["set"] = d.fields.get("set").cloned().unwrap_or(Value::Null);
p["action"] = d.fields.get("action").cloned().unwrap_or(Value::Null);
p["name"] = json!(name);
app.run(crate::panels::actions::ACTION_OPTIONS, p)?;
} else if let Some(set) = d.fields.get("set") {
let s = set.as_u64().and_then(|i| usize::try_from(i).ok()).and_then(|i| app.ui.action_sets.get_mut(i)).ok_or("no such action set")?;
s.name = name;
+12
View File
@@ -5476,6 +5476,11 @@ theme Appearance Външен вид
Export Type: Тип на експортиране:
Movie Clip Филмов клип
@msg name is empty името е празно
@msg an action is already recording вече се записва действие
@msg no such function key няма такъв функционален клавиш
@msg no such color няма такъв цвят
@msg {_1} cannot be used on Windows {_1} не може да се използва в Windows
@msg more than one action is named “{_1}” повече от едно действие се казва „{_1}“
@msg no symbol named `{n}` няма символ с име `{n}`
Smudge Stick… Размазваща пръчка…
Smudge Stick Размазваща пръчка
@@ -5622,6 +5627,13 @@ axis Y Axis Y ос
Action Options… Опции на действието…
Action Options Опции на действието
Rename Action Преименуване на действие
New Action… Ново действие…
New Action Ново действие
Create New Action Създаване на ново действие
Play Action Изпълнение на действие
Action Set: Набор от действия:
Function Key: Функционален клавиш:
Record Запис
Create New Set Създаване на нов набор
Stop Global Edit Край на глобалното редактиране
Global Edit Options Опции за глобално редактиране
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5480,6 +5480,11 @@ mark-style Japanese Japanski
Export Type: Vrsta izvoza:
Movie Clip Filmski klip
@msg name is empty naziv je prazan
@msg an action is already recording akcija se već snima
@msg no such function key nema takve funkcijske tipke
@msg no such color nema takve boje
@msg {_1} cannot be used on Windows {_1} se ne može koristiti na Windowsu
@msg more than one action is named “{_1}” više od jedne akcije ima naziv „{_1}”
@msg no symbol named `{n}` nema simbola pod nazivom `{n}`
Smudge Stick… Štapić za razmazivanje…
Smudge Stick Štapić za razmazivanje
@@ -5645,6 +5650,13 @@ axis Y Axis Y osa
Action Options… Opcije akcije…
Action Options Opcije akcije
Rename Action Preimenuj akciju
New Action… Nova akcija…
New Action Nova akcija
Create New Action Napravi novu akciju
Play Action Reprodukuj akciju
Action Set: Skup akcija:
Function Key: Funkcijska tipka:
Record Snimi
Create New Set Napravi novi skup
Stop Global Edit Zaustavi globalno uređivanje
Global Edit Options Opcije globalnog uređivanja
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -3774,6 +3774,13 @@ digits Malayalam Malaiàlam
Action Options… Opcions de l’acció…
Action Options Opcions de l’acció
Rename Action Canvia el nom de l’acció
New Action… Acció nova…
New Action Acció nova
Create New Action Crea una acció nova
Play Action Reprodueix l’acció
Action Set: Conjunt d’accions:
Function Key: Tecla de funció:
Record Enregistra
Set Options… Defineix les opcions…
Set Preference Defineix la preferència
Set Slice Rectangle Defineix el rectangle del tall
@@ -5160,6 +5167,11 @@ digits Malayalam Malaiàlam
@msg move requires an existing destination panel per moure cal un panell de destinació existent
@msg Multichannel PSD files can't be read: save it in RGB, CMYK or Grayscale mode Els fitxers PSD multicanal no es poden llegir: deseu-los en mode RGB, CMYK o escala de grisos
@msg name is empty el nom és buit
@msg an action is already recording ja s’està enregistrant una acció
@msg no such function key no existeix aquesta tecla de funció
@msg no such color no existeix aquest color
@msg {_1} cannot be used on Windows {_1} no es pot fer servir al Windows
@msg more than one action is named “{_1}” més d’una acció es diu “{_1}”
@msg name the file poseu un nom al fitxer
@msg New Window isn't available yet: a document opens in one window Finestra nova encara no està disponible: un document s’obre en una sola finestra
@msg no active document no hi ha cap document actiu
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5567,6 +5567,11 @@ mark-style Japanese Japonské
Export Type: Typ exportu:
Movie Clip Filmový klip
@msg name is empty název je prázdný
@msg an action is already recording akce se už zaznamenává
@msg no such function key taková funkční klávesa neexistuje
@msg no such color taková barva neexistuje
@msg {_1} cannot be used on Windows Zkratku {_1} nelze ve Windows použít
@msg more than one action is named “{_1}” název „{_1}“ má více než jedna akce
@msg no symbol named `{n}` žádný symbol s názvem `{n}`
Smudge Stick… Rozmazávací tyčinka…
Smudge Stick Rozmazávací tyčinka
@@ -5737,6 +5742,13 @@ axis Y Axis osa Y
Action Options… Možnosti akce…
Action Options Možnosti akce
Rename Action Přejmenovat akci
New Action… Nová akce…
New Action Nová akce
Create New Action Vytvořit novou akci
Play Action Přehrát akci
Action Set: Sada akcí:
Function Key: Funkční klávesa:
Record Zaznamenat
Create New Set Vytvořit novou sadu
Stop Global Edit Ukončit globální úpravy
Global Edit Options Možnosti globálních úprav
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5360,6 +5360,11 @@ swatch Bright Violet Kraftig violet
Export Type: Eksporttype:
Movie Clip Filmklip
@msg name is empty navnet er tomt
@msg an action is already recording en handling optages allerede
@msg no such function key ingen sådan funktionstast
@msg no such color ingen sådan farve
@msg {_1} cannot be used on Windows {_1} kan ikke bruges i Windows
@msg more than one action is named “{_1}” mere end én handling hedder »{_1}«
@msg no symbol named `{n}` intet symbol med navnet `{n}`
Remove Color Profile… Fjern farveprofil…
Color wheel Farvehjul
@@ -5639,6 +5644,13 @@ axis Y Axis Y-akse
Action Options… Indstillinger for handling…
Action Options Indstillinger for handling
Rename Action Omdøb handling
New Action… Ny handling…
New Action Ny handling
Create New Action Opret ny handling
Play Action Afspil handling
Action Set: Handlingssæt:
Function Key: Funktionstast:
Record Optag
Create New Set Opret nyt sæt
Stop Global Edit Stop global redigering
Global Edit Options Indstillinger for global redigering
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5145,6 +5145,11 @@ effect Soft Weich
Export Type: Exporttyp:
Movie Clip Movieclip
@msg name is empty Name ist leer
@msg an action is already recording eine Aktion wird bereits aufgezeichnet
@msg no such function key keine solche Funktionstaste
@msg no such color keine solche Farbe
@msg {_1} cannot be used on Windows {_1} kann unter Windows nicht verwendet werden
@msg more than one action is named “{_1}” mehr als eine Aktion heißt „{_1}“
@msg no symbol named `{n}` kein Symbol namens `{n}`
Smudge Stick… Wischstift…
Smudge Stick Wischstift
@@ -5319,6 +5324,13 @@ axis Y Axis Y-Achse
Action Options… Aktionsoptionen…
Action Options Aktionsoptionen
Rename Action Aktion umbenennen
New Action… Neue Aktion…
New Action Neue Aktion
Create New Action Neue Aktion erstellen
Play Action Aktion abspielen
Action Set: Aktionssatz:
Function Key: Funktionstaste:
Record Aufzeichnen
Create New Set Neuen Satz erstellen
Stop Global Edit Globale Bearbeitung beenden
Global Edit Options Optionen für globale Bearbeitung
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5518,6 +5518,11 @@ effect Points Σημεία
Export Type: Τύπος εξαγωγής:
Movie Clip Κλιπ ταινίας
@msg name is empty το όνομα είναι κενό
@msg an action is already recording μια ενέργεια καταγράφεται ήδη
@msg no such function key δεν υπάρχει τέτοιο πλήκτρο λειτουργίας
@msg no such color δεν υπάρχει τέτοιο χρώμα
@msg {_1} cannot be used on Windows Το {_1} δεν μπορεί να χρησιμοποιηθεί στα Windows
@msg more than one action is named “{_1}” περισσότερες από μία ενέργειες ονομάζονται «{_1}»
@msg no symbol named `{n}` κανένα σύμβολο με όνομα `{n}`
Smudge Stick… Μουτζούρα…
Smudge Stick Μουτζούρα
@@ -5688,6 +5693,13 @@ axis Y Axis Άξονας Y
Action Options… Επιλογές ενέργειας…
Action Options Επιλογές ενέργειας
Rename Action Μετονομασία ενέργειας
New Action… Νέα ενέργεια…
New Action Νέα ενέργεια
Create New Action Δημιουργία νέας ενέργειας
Play Action Αναπαραγωγή ενέργειας
Action Set: Σύνολο ενεργειών:
Function Key: Πλήκτρο λειτουργίας:
Record Καταγραφή
Create New Set Δημιουργία νέου συνόλου
Stop Global Edit Τερματισμός καθολικής επεξεργασίας
Global Edit Options Επιλογές καθολικής επεξεργασίας
Can't render this file because it contains an unexpected character in line 163 and column 5.
+12
View File
@@ -5508,6 +5508,11 @@ mark-style Japanese Japonesas
Export Type: Tipo de exportación:
Movie Clip Clip de película
@msg name is empty el nombre está vacío
@msg an action is already recording ya se está grabando una acción
@msg no such function key no existe esa tecla de función
@msg no such color no existe ese color
@msg {_1} cannot be used on Windows {_1} no se puede usar en Windows
@msg more than one action is named “{_1}” más de una acción se llama “{_1}”
@msg no symbol named `{n}` no hay ningún símbolo llamado `{n}`
Smudge Stick… Difuminar con barra…
Smudge Stick Difuminar con barra
@@ -5678,6 +5683,13 @@ axis Y Axis Eje Y
Action Options… Opciones de acción…
Action Options Opciones de acción
Rename Action Cambiar nombre de acción
New Action… Nueva acción…
New Action Nueva acción
Create New Action Crear nueva acción
Play Action Reproducir acción
Action Set: Conjunto de acciones:
Function Key: Tecla de función:
Record Grabar
Create New Set Crear nuevo conjunto
Stop Global Edit Detener edición global
Global Edit Options Opciones de edición global
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5530,6 +5530,11 @@ mark-style Japanese Japanilainen
Export Type: Vientityyppi:
Movie Clip Elokuvaleike
@msg name is empty nimi on tyhjä
@msg an action is already recording toimintoa nauhoitetaan jo
@msg no such function key toimintonäppäintä ei ole
@msg no such color väriä ei ole
@msg {_1} cannot be used on Windows {_1} ei ole käytettävissä Windowsissa
@msg more than one action is named “{_1}” useamman kuin yhden toiminnon nimi on ”{_1}”
@msg no symbol named `{n}` symbolia nimeltä `{n}` ei ole
Smudge Stick… Sumennuskynä…
Smudge Stick Sumennuskynä
@@ -5767,6 +5772,13 @@ axis Y Axis Y-akseli
Action Options… Toiminnon asetukset…
Action Options Toiminnon asetukset
Rename Action Nimeä toiminto uudelleen
New Action… Uusi toiminto…
New Action Uusi toiminto
Create New Action Luo uusi toiminto
Play Action Toista toiminto
Action Set: Toimintosarja:
Function Key: Toimintonäppäin:
Record Nauhoita
Create New Set Luo uusi sarja
Stop Global Edit Lopeta yleismuokkaus
Global Edit Options Yleismuokkauksen asetukset
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5562,6 +5562,11 @@ theme Appearance Apparence
Export Type: Type d'exportation :
Movie Clip Clip
@msg name is empty le nom est vide
@msg an action is already recording un script est déjà en cours d’enregistrement
@msg no such function key touche de fonction inexistante
@msg no such color couleur inexistante
@msg {_1} cannot be used on Windows {_1} ne peut pas être utilisé sous Windows
@msg more than one action is named “{_1}” plusieurs scripts s’appellent « {_1} »
@msg no symbol named `{n}` aucun symbole nommé `{n}`
Smudge Stick… Estompe…
Smudge Stick Estompe
@@ -5732,6 +5737,13 @@ axis Y Axis Axe Y
Action Options… Options de script…
Action Options Options de script
Rename Action Renommer le script
New Action… Nouveau script…
New Action Nouveau script
Create New Action Créer un script
Play Action Exécuter le script
Action Set: Jeu de scripts :
Function Key: Touche de fonction :
Record Enregistrer
Create New Set Créer un jeu
Stop Global Edit Arrêter la modification globale
Global Edit Options Options de modification globale
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5550,6 +5550,11 @@ imageTrace Outline Körvonal
Export Type: Exportálás típusa:
Movie Clip Mozgóklip
@msg name is empty a név üres
@msg an action is already recording már folyik egy művelet felvétele
@msg no such function key nincs ilyen funkcióbillentyű
@msg no such color nincs ilyen szín
@msg {_1} cannot be used on Windows A(z) {_1} nem használható Windows rendszeren
@msg more than one action is named “{_1}” több művelet neve is „{_1}”
@msg no symbol named `{n}` nincs `{n}` nevű szimbólum
Smudge Stick… Elmosó rúd…
Smudge Stick Elmosó rúd
@@ -5720,6 +5725,13 @@ axis Y Axis Y tengely
Action Options… Művelet beállításai…
Action Options Művelet beállításai
Rename Action Művelet átnevezése
New Action… Új művelet…
New Action Új művelet
Create New Action Új művelet létrehozása
Play Action Művelet lejátszása
Action Set: Műveletkészlet:
Function Key: Funkcióbillentyű:
Record Felvétel
Create New Set Új készlet létrehozása
Stop Global Edit Globális szerkesztés befejezése
Global Edit Options Globális szerkesztés beállításai
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5360,6 +5360,11 @@ swatch Bright Violet Violet cerah
Export Type: Jenis ekspor:
Movie Clip Klip film
@msg name is empty nama kosong
@msg an action is already recording sebuah tindakan sedang direkam
@msg no such function key tidak ada tombol fungsi seperti itu
@msg no such color tidak ada warna seperti itu
@msg {_1} cannot be used on Windows {_1} tidak dapat digunakan di Windows
@msg more than one action is named “{_1}” lebih dari satu tindakan bernama “{_1}”
@msg no symbol named `{n}` tidak ada simbol bernama `{n}`
Remove Color Profile… Hapus profil warna…
Color wheel Roda warna
@@ -5639,6 +5644,13 @@ axis Y Axis Sumbu Y
Action Options… Opsi tindakan…
Action Options Opsi tindakan
Rename Action Ganti nama tindakan
New Action… Tindakan baru…
New Action Tindakan baru
Create New Action Buat tindakan baru
Play Action Putar tindakan
Action Set: Set tindakan:
Function Key: Tombol fungsi:
Record Rekam
Create New Set Buat set baru
Stop Global Edit Hentikan edit global
Global Edit Options Opsi edit global
Can't render this file because it contains an unexpected character in line 2211 and column 5.
+12
View File
@@ -5180,6 +5180,11 @@ lighting Light Luce
Export Type: Tipo di esportazione:
Movie Clip Clip filmato
@msg name is empty il nome è vuoto
@msg an action is already recording è già in corso la registrazione di un’azione
@msg no such function key tasto funzione inesistente
@msg no such color colore inesistente
@msg {_1} cannot be used on Windows {_1} non può essere usato su Windows
@msg more than one action is named “{_1}” più di un’azione si chiama “{_1}”
@msg no symbol named `{n}` nessun simbolo denominato `{n}`
Smudge Stick… Sfumino…
Smudge Stick Sfumino
@@ -5353,6 +5358,13 @@ axis Y Axis Asse Y
Action Options… Opzioni azione…
Action Options Opzioni azione
Rename Action Rinomina azione
New Action… Nuova azione…
New Action Nuova azione
Create New Action Crea nuova azione
Play Action Esegui azione
Action Set: Set di azioni:
Function Key: Tasto funzione:
Record Registra
Create New Set Crea nuovo set
Stop Global Edit Interrompi modifica globale
Global Edit Options Opzioni modifica globale
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5223,6 +5223,11 @@ lighting Light ライト
Export Type: 書き出しタイプ:
Movie Clip ムービークリップ
@msg name is empty 名前が空です
@msg an action is already recording すでにアクションを記録中です
@msg no such function key 指定されたファンクションキーが見つかりません
@msg no such color 指定されたカラーが見つかりません
@msg {_1} cannot be used on Windows {_1} は Windows では使用できません
@msg more than one action is named “{_1}” 「{_1}」という名前のアクションが複数あります
@msg no symbol named `{n}` `{n}` という名前のシンボルはありません
Smudge Stick… スマッジスティック…
Smudge Stick スマッジスティック
@@ -5418,6 +5423,13 @@ axis Y Axis Y 軸
Action Options… アクションオプション…
Action Options アクションオプション
Rename Action アクション名を変更
New Action… 新規アクション…
New Action 新規アクション
Create New Action 新規アクションを作成
Play Action アクションを再生
Action Set: アクションセット:
Function Key: ファンクションキー:
Record 記録
Create New Set 新規セットを作成
Stop Global Edit グローバル編集を終了
Global Edit Options グローバル編集オプション
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5267,6 +5267,11 @@ imageTrace Outline კონტური
Export Type: ექსპორტის ტიპი:
Movie Clip ანიმაციური კლიპი
@msg name is empty სახელი ცარიელია
@msg an action is already recording მოქმედება უკვე იწერება
@msg no such function key ასეთი ფუნქციური კლავიში არ არის
@msg no such color ასეთი ფერი არ არის
@msg {_1} cannot be used on Windows {_1} ვერ გამოიყენება Windows-ში
@msg more than one action is named “{_1}” „{_1}“ ერთზე მეტი მოქმედების სახელია
@msg no symbol named `{n}` სიმბოლო სახელით `{n}` არ არის
@msg no saved selection recalled შენახული მონიშვნა გამოძახებული არ არის
@msg The last start of VectorCraft ended on {name} before its window appeared, so it started on {summary}. To try that graphics processor again, change Preferences › Performance › Graphics Processor or start with WGPU_BACKEND set VectorCraft-ის ბოლო გაშვება ფანჯრის გამოჩენამდე შეწყდა (გრაფიკული პროცესორი: {name}), ამიტომ VectorCraft გაეშვა: {summary}. ამ გრაფიკული პროცესორის ხელახლა საცდელად შეცვალეთ პარამეტრები › წარმადობა › გრაფიკული პროცესორი ან გაუშვით WGPU_BACKEND ცვლადის მითითებით
@@ -5651,6 +5656,13 @@ axis Y Axis Y ღერძი
Action Options… მოქმედების პარამეტრები…
Action Options მოქმედების პარამეტრები
Rename Action მოქმედების სახელის შეცვლა
New Action… ახალი მოქმედება…
New Action ახალი მოქმედება
Create New Action ახალი მოქმედების შექმნა
Play Action მოქმედების შესრულება
Action Set: მოქმედებების ნაკრები:
Function Key: ფუნქციური კლავიში:
Record ჩაწერა
Create New Set ახალი ნაკრების შექმნა
Stop Global Edit გლობალური რედაქტირების დასრულება
Global Edit Options გლობალური რედაქტირების პარამეტრები
Can't render this file because it is too large.
+12
View File
@@ -5141,6 +5141,11 @@ lighting Light 광원
Export Type: 내보내기 유형:
Movie Clip 무비 클립
@msg name is empty 이름이 비어 있습니다
@msg an action is already recording 이미 액션을 기록하고 있습니다
@msg no such function key 해당 기능 키가 없습니다
@msg no such color 해당 색상이 없습니다
@msg {_1} cannot be used on Windows {_1}은(는) Windows에서 사용할 수 없습니다
@msg more than one action is named “{_1}” “{_1}”(이)라는 이름의 액션이 둘 이상 있습니다
@msg no symbol named `{n}` 이름이 `{n}`인 심볼이 없습니다
Smudge Stick… 문지르기 막대…
Smudge Stick 문지르기 막대
@@ -5314,6 +5319,13 @@ axis Y Axis Y축
Action Options… 액션 옵션…
Action Options 액션 옵션
Rename Action 액션 이름 바꾸기
New Action… 새 액션…
New Action 새 액션
Create New Action 새 액션 만들기
Play Action 액션 재생
Action Set: 액션 세트:
Function Key: 기능 키:
Record 기록
Create New Set 새 세트 만들기
Stop Global Edit 전체 편집 중지
Global Edit Options 전체 편집 옵션
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5368,6 +5368,11 @@ swatch Bright Violet Felviolet
Export Type: Exporttype:
Movie Clip Filmclip
@msg name is empty naam is leeg
@msg an action is already recording er wordt al een actie opgenomen
@msg no such function key functietoets bestaat niet
@msg no such color kleur bestaat niet
@msg {_1} cannot be used on Windows {_1} kan niet worden gebruikt in Windows
@msg more than one action is named “{_1}” meer dan één actie heet „{_1}”
@msg no symbol named `{n}` geen symbool met de naam `{n}`
Remove Color Profile… Kleurprofiel verwijderen…
Color wheel Kleurenwiel
@@ -5683,6 +5688,13 @@ axis Y Axis Y-as
Action Options… Actieopties…
Action Options Actieopties
Rename Action Actie hernoemen
New Action… Nieuwe actie…
New Action Nieuwe actie
Create New Action Nieuwe actie maken
Play Action Actie afspelen
Action Set: Actieset:
Function Key: Functietoets:
Record Opnemen
Create New Set Nieuwe set maken
Stop Global Edit Globale bewerking stoppen
Global Edit Options Opties voor globale bewerking
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5420,6 +5420,11 @@ mark-style Japanese Japońskie
Export Type: Typ eksportu:
Movie Clip Klip filmowy
@msg name is empty nazwa jest pusta
@msg an action is already recording operacja jest już nagrywana
@msg no such function key brak takiego klawisza funkcyjnego
@msg no such color brak takiego koloru
@msg {_1} cannot be used on Windows Skrótu {_1} nie można używać w systemie Windows
@msg more than one action is named “{_1}” więcej niż jedna operacja nazywa się „{_1}”
@msg no symbol named `{n}` brak symbolu o nazwie `{n}`
Smudge Stick… Rozmazywacz…
Smudge Stick Rozmazywacz
@@ -5590,6 +5595,13 @@ axis Y Axis Oś Y
Action Options… Opcje operacji…
Action Options Opcje operacji
Rename Action Zmień nazwę operacji
New Action… Nowa operacja…
New Action Nowa operacja
Create New Action Utwórz nową operację
Play Action Odtwórz operację
Action Set: Zestaw operacji:
Function Key: Klawisz funkcyjny:
Record Nagraj
Create New Set Utwórz nowy zestaw
Stop Global Edit Zakończ edycję globalną
Global Edit Options Opcje edycji globalnej
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5482,6 +5482,11 @@ mark-style Japanese Japonesas
# Symbol Options › Export Type
@msg name is empty o nome está vazio
@msg an action is already recording uma ação já está sendo gravada
@msg no such function key tecla de função inexistente
@msg no such color cor inexistente
@msg {_1} cannot be used on Windows {_1} não pode ser usado no Windows
@msg more than one action is named “{_1}” mais de uma ação se chama “{_1}”
@msg no symbol named `{n}` nenhum símbolo chamado `{n}`
Smudge Stick… Esfuminho…
Smudge Stick Esfuminho
@@ -5652,6 +5657,13 @@ axis Y Axis Eixo Y
Action Options… Opções da Ação…
Action Options Opções da Ação
Rename Action Renomear Ação
New Action… Nova Ação…
New Action Nova Ação
Create New Action Criar Nova Ação
Play Action Reproduzir Ação
Action Set: Conjunto de Ações:
Function Key: Tecla de Função:
Record Gravar
Create New Set Criar Novo Conjunto
Stop Global Edit Parar Edição Global
Global Edit Options Opções de Edição Global
Can't render this file because it contains an unexpected character in line 6 and column 47.
+12
View File
@@ -5175,6 +5175,11 @@ lighting Light Свет
Export Type: Тип экспорта:
Movie Clip Видеоклип
@msg name is empty имя пустое
@msg an action is already recording действие уже записывается
@msg no such function key такой функциональной клавиши нет
@msg no such color такого цвета нет
@msg {_1} cannot be used on Windows Сочетание {_1} нельзя использовать в Windows
@msg more than one action is named “{_1}” несколько действий называются «{_1}»
@msg no symbol named `{n}` нет символа с именем `{n}`
Smudge Stick… Растушёвка…
Smudge Stick Растушёвка
@@ -5348,6 +5353,13 @@ axis Y Axis Ось Y
Action Options… Параметры действия…
Action Options Параметры действия
Rename Action Переименовать действие
New Action… Новое действие…
New Action Новое действие
Create New Action Создать новое действие
Play Action Воспроизвести действие
Action Set: Набор действий:
Function Key: Функциональная клавиша:
Record Записать
Create New Set Создать новый набор
Stop Global Edit Завершить глобальное редактирование
Global Edit Options Параметры глобального редактирования
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5522,6 +5522,11 @@ theme Appearance Utseende
Export Type: Exporttyp:
Movie Clip Filmklipp
@msg name is empty namnet är tomt
@msg an action is already recording en åtgärd spelas redan in
@msg no such function key funktionstangenten finns inte
@msg no such color färgen finns inte
@msg {_1} cannot be used on Windows {_1} kan inte användas i Windows
@msg more than one action is named “{_1}” fler än en åtgärd heter ”{_1}”
@msg no symbol named `{n}` ingen symbol med namnet `{n}`
Angular Vinkelmått
Away from the Line Bort från linjen
@@ -5760,6 +5765,13 @@ axis Y Axis Y-axel
Action Options… Alternativ för åtgärd…
Action Options Alternativ för åtgärd
Rename Action Byt namn på åtgärd
New Action… Ny åtgärd…
New Action Ny åtgärd
Create New Action Skapa ny åtgärd
Play Action Spela upp åtgärd
Action Set: Åtgärdsuppsättning:
Function Key: Funktionstangent:
Record Spela in
Create New Set Skapa ny uppsättning
Stop Global Edit Avsluta global redigering
Global Edit Options Alternativ för global redigering
Can't render this file because it contains an unexpected character in line 5 and column 25.
+12
View File
@@ -5232,6 +5232,11 @@ theme Appearance Görünüm
Export Type: İhracat Türü:
Movie Clip Film Klibi
@msg name is empty isim boş
@msg an action is already recording zaten bir eylem kaydediliyor
@msg no such function key öyle bir işlev tuşu yok
@msg no such color öyle bir renk yok
@msg {_1} cannot be used on Windows {_1} Windows'ta kullanılamaz
@msg more than one action is named “{_1}” birden fazla eylemin adı “{_1}”
@msg no symbol named `{n}` `{n}` adında bir sembol yok
Artboard Options: edit with the Artboard tool Çalışma Yüzeyi Seçenekleri: Çalışma Yüzeyi aracıyla düzenleme
@msg this is a PostScript file (an .ai saved in an older format or without PDF compatibility, or an EPS file), which can't be opened yet: save it as PDF, PDF-compatible .ai or SVG bu henüz açılamayan bir PostScript dosyasıdır (eski bir formatta kaydedilmiş veya PDF uyumluluğu olmayan bir .ai veya bir EPS dosyası): PDF, PDF uyumlu .ai veya SVG olarak kaydedin
@@ -5694,6 +5699,13 @@ axis Y Axis Y ekseni
Action Options… Eylem Seçenekleri…
Action Options Eylem Seçenekleri
Rename Action Eylemi Yeniden Adlandır
New Action… Yeni Eylem…
New Action Yeni Eylem
Create New Action Yeni Eylem Oluştur
Play Action Eylemi Oynat
Action Set: Eylem Seti:
Function Key: İşlev Tuşu:
Record Kayıt
Create New Set Yeni Set Oluştur
Stop Global Edit Genel Düzenlemeyi Durdur
Global Edit Options Genel Düzenleme Seçenekleri
Can't render this file because it contains an unexpected character in line 5 and column 25.
+12
View File
@@ -5160,6 +5160,11 @@ lighting Light Світло
Export Type: Тип експорту:
Movie Clip Кліп
@msg name is empty ім’я порожнє
@msg an action is already recording дія вже записується
@msg no such function key такої функціональної клавіші немає
@msg no such color такого кольору немає
@msg {_1} cannot be used on Windows Сполучення {_1} не можна використовувати у Windows
@msg more than one action is named “{_1}” кілька дій мають назву «{_1}»
@msg no symbol named `{n}` немає символу з назвою `{n}`
Smudge Stick… Розтушовування…
Smudge Stick Розтушовування
@@ -5333,6 +5338,13 @@ axis Y Axis Вісь Y
Action Options… Параметри дії…
Action Options Параметри дії
Rename Action Перейменувати дію
New Action… Нова дія…
New Action Нова дія
Create New Action Створити нову дію
Play Action Відтворити дію
Action Set: Набір дій:
Function Key: Функціональна клавіша:
Record Записати
Create New Set Створити новий набір
Stop Global Edit Завершити глобальне редагування
Global Edit Options Параметри глобального редагування
Can't render this file because it contains an unexpected character in line 177 and column 5.
+12
View File
@@ -5161,6 +5161,11 @@ theme Appearance Giao diện
Export Type: Kiểu xuất:
Movie Clip Clip phim
@msg name is empty tên trống
@msg an action is already recording đang ghi một hành động
@msg no such function key không có phím chức năng như vậy
@msg no such color không có màu như vậy
@msg {_1} cannot be used on Windows không thể dùng {_1} trên Windows
@msg more than one action is named “{_1}” có nhiều hành động tên là “{_1}”
@msg no symbol named `{n}` không có biểu tượng nào tên `{n}`
Smudge Stick… Bút chì xóa mờ…
Smudge Stick Bút chì xóa mờ
@@ -5334,6 +5339,13 @@ axis Y Axis Trục Y
Action Options… Tùy chọn hành động…
Action Options Tùy chọn hành động
Rename Action Đổi tên hành động
New Action… Hành động mới…
New Action Hành động mới
Create New Action Tạo hành động mới
Play Action Phát hành động
Action Set: Bộ hành động:
Function Key: Phím chức năng:
Record Ghi
Create New Set Tạo bộ mới
Stop Global Edit Dừng chỉnh sửa toàn cục
Global Edit Options Tùy chọn chỉnh sửa toàn cục
Can't render this file because it contains an unexpected character in line 199 and column 5.
+12
View File
@@ -5400,6 +5400,11 @@ lighting Light 光源
Export Type: 导出类型:
Movie Clip 影片剪辑
@msg name is empty 名称为空
@msg an action is already recording 已在记录动作
@msg no such function key 没有此功能键
@msg no such color 没有此颜色
@msg {_1} cannot be used on Windows {_1} 在 Windows 上不能使用
@msg more than one action is named “{_1}” 有多个动作名为“{_1}”
@msg no symbol named `{n}` 没有名为 `{n}` 的符号
Smudge Stick… 涂抹棒…
Smudge Stick 涂抹棒
@@ -5575,6 +5580,13 @@ axis Y Axis Y 轴
Action Options… 动作选项…
Action Options 动作选项
Rename Action 重命名动作
New Action… 新建动作…
New Action 新建动作
Create New Action 创建新动作
Play Action 播放动作
Action Set: 动作组:
Function Key: 功能键:
Record 记录
Create New Set 创建新组
Stop Global Edit 停止全局编辑
Global Edit Options 全局编辑选项
Can't render this file because it contains an unexpected character in line 2 and column 73.
+12
View File
@@ -5217,6 +5217,11 @@ lighting Light 光源
Export Type: 轉存類型:
Movie Clip 影片片段
@msg name is empty 名稱為空
@msg an action is already recording 已在錄製動作
@msg no such function key 沒有這個功能鍵
@msg no such color 沒有這個顏色
@msg {_1} cannot be used on Windows {_1} 無法在 Windows 上使用
@msg more than one action is named “{_1}” 有多個動作名為「{_1}」
@msg no symbol named `{n}` 沒有名為 `{n}` 的符號
Smudge Stick… 塗抹棒…
Smudge Stick 塗抹棒
@@ -5371,6 +5376,13 @@ axis Y Axis Y 軸
Action Options… 動作選項…
Action Options 動作選項
Rename Action 重新命名動作
New Action… 新增動作…
New Action 新增動作
Create New Action 建立新動作
Play Action 播放動作
Action Set: 動作組:
Function Key: 功能鍵:
Record 錄製
Create New Set 建立新組
Stop Global Edit 停止整體編輯
Global Edit Options 整體編輯選項
Can't render this file because it contains an unexpected character in line 6 and column 47.
+4
View File
@@ -815,6 +815,10 @@ fn run_ui_part11(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<Result
}
"ui.packageDialog" => crate::dialogs::package::open(app),
crate::panels::actions::RENAME_ACTION => crate::panels::actions::rename_action(app, p),
crate::panels::actions::NEW_ACTION => crate::panels::actions::new_action(app, p),
crate::panels::actions::ACTION_OPTIONS => crate::panels::actions::action_options(app, p),
crate::panels::actions::PLAY_ACTION => crate::panels::actions::play_action(app, p),
crate::panels::actions::STOP_RECORDING => crate::panels::actions::stop(app, p),
"ui.batchDialog" => {
let set = p.get("set").and_then(Value::as_u64).unwrap_or(0) as usize;
let action = p.get("action").and_then(Value::as_u64).unwrap_or(0) as usize;
+25 -1
View File
@@ -1180,7 +1180,31 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
crate::panels::actions::RENAME_ACTION,
"Rename Action",
"",
"{set: index, action: index, name} rename the Actions panel's action at action in set (0 is the top set) to name, with spaces trimmed from both ends; its steps stay. The panel menu's Action Options… (dialog `actionSetOptions` with set, action and name) runs this for the selected action. An index past the last set or action, or an empty name, is an error and renames nothing → {name}",
"{set: index, action: index, name} rename the Actions panel's action at action in set (0 is the top set) to name, with spaces trimmed from both ends; its steps, function key and color stay. An index past the last set or action, or an empty name, is an error and renames nothing → {name}",
),
(
crate::panels::actions::NEW_ACTION,
"New Action",
"",
"{set: index, name, key?: 0-15, cmd?, shift?, color?: red|yellow|green|blue|violet} add an action named name (spaces trimmed from both ends) after the last action of the Actions panel's set at set (0 is the top set) and start recording into it; Stop Playing/Recording (ui.action.stop) ends the recording. key 1 to 15 is the function key F1 to F15 that plays the action (0 or null: none), with cmd (Ctrl, Command on macOS) and shift; color is its Button Mode color (null or \"\": none), which the panel does not show. Action function keys take priority over command shortcuts and preserve the command's binding. On Windows F1, Ctrl+F4 and Ctrl+F6 cannot be used. The set becomes current and the new action is selected. The panel's Create New Action button and menu's New Action… (dialog `actionNew` with set, name, key, cmd, shift and color) run this on Record. While an action is recording, and for an index past the last set, an empty name, or a key or color that is not one of these, it is an error and nothing is added → {set, action}",
),
(
crate::panels::actions::ACTION_OPTIONS,
"Action Options",
"",
"{set: index, action: index, name?, key?: 0-15, cmd?, shift?, color?: red|yellow|green|blue|violet} change the Actions panel's action at action in set (0 is the top set); its steps stay. name renames it (spaces trimmed from both ends), key 1 to 15 with cmd (Ctrl, Command on macOS) and shift sets the function key F1 to F15 that plays it (0 or null: none), and color sets its Button Mode color (null or \"\": none); a param left out keeps what the action has, and cmd or shift alone changes that modifier of its key. Action function keys take priority over command shortcuts and preserve the command's binding. The panel menu's Action Options… (dialog `actionSetOptions` with set, action, name, key, cmd, shift and color) runs this for the selected action. An index past the last set or action, an empty name, or a key or color that is not one of these is an error and changes nothing → {name, key, color}",
),
(
crate::panels::actions::PLAY_ACTION,
"Play Action",
"",
"{action: name, set?: name} play the Actions panel's action named action as one undoable batch; set names the set to look in (default: every set). A name no action has, or one that more than one action in the sets looked in has, is an error and nothing plays → what command.batch returns",
),
(
crate::panels::actions::STOP_RECORDING,
"Stop Playing/Recording",
"",
"{} end the Actions panel's recording and keep its steps, in the action ui.action.new made for it, else in a new action after the last action of its set, as the panel's Stop Playing/Recording button does. With nothing recording it changes nothing → {stopped}",
),
(
"ui.batchDialog",
File diff suppressed because it is too large Load Diff
+19 -6
View File
@@ -1,8 +1,10 @@
//! Action set files: the Actions panel menu's Save Actions… and Load Actions….
//!
//! An action set file (`.vcactions`) is JSON: `{"format": "vcactions", "version": 1, "name",
//! "actions": [{"name", "steps": [{"command", "params"}]}]}`. Each step is a command id and its
//! params, as `command.batch` takes them.
//! "actions": [{"name", "steps": [{"command", "params"}], "key"?, "color"?}]}`. Each step is a
//! command id and its params, as `command.batch` takes them. `key` is the action's function key
//! (`{"key": 1 to 15, "cmd", "shift"}`) and `color` its Button Mode color; an action without them,
//! or with a value that is not one, has none.
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
@@ -42,6 +44,10 @@ struct SetFile {
struct FileAction {
name: String,
steps: Vec<FileStep>,
#[serde(default, skip_serializing_if = "Option::is_none", deserialize_with = "super::deserialize_key")]
key: Option<super::FunctionKey>,
#[serde(default, skip_serializing_if = "Option::is_none", deserialize_with = "super::deserialize_color")]
color: Option<String>,
}
/// A step of an action in an action set file: a command id and its params, as `command.batch`
@@ -61,6 +67,8 @@ pub fn write_set(set: &ActionSet) -> String {
.map(|a| FileAction {
name: a.name.clone(),
steps: a.steps.iter().map(|(command, params)| FileStep { command: command.clone(), params: params.clone() }).collect(),
key: a.key,
color: a.color.clone(),
})
.collect();
let file = SetFile { format: ACTIONS_EXT.into(), version: 1, name: set.name.clone(), actions };
@@ -85,8 +93,11 @@ pub fn read_set(text: &str, name: &str) -> Result<ActionSet, String> {
if f.actions.iter().any(|a| a.steps.len() > MAX_ACTION_STEPS) {
return Err("an action in the action set file has more than 10,000 steps".into());
}
let actions =
f.actions.into_iter().map(|a| Action { name: a.name, steps: a.steps.into_iter().map(|s| (s.command, s.params)).collect() }).collect();
let actions = f
.actions
.into_iter()
.map(|a| Action { key: a.key, color: a.color, ..Action::new(a.name, a.steps.into_iter().map(|s| (s.command, s.params)).collect()) })
.collect();
let set_name = if f.name.trim().is_empty() { name.to_string() } else { f.name };
Ok(ActionSet::new(set_name, actions))
}
@@ -151,8 +162,10 @@ pub(crate) fn can_load(app: &VectorcraftApp) -> bool {
/// `ui.actionSet.load {path? | data?}`: reads the action set file at `path` (else a picked one), or
/// the file's text `data`, and adds its set after the others, with its actions. A set with the
/// same name as one in the panel gets the next free number (`Print 2`). The current set and the
/// other sets stay as they are → `{set: index, name, actions: n}`.
/// same name as one in the panel gets the next free number (`Print 2`). A loaded action whose
/// function key an action in the panel or a command, tool or panel already has, or that cannot be
/// used on this platform, gets no key. The current set and the other sets stay as they are →
/// `{set: index, name, actions: n}`.
pub fn load_set(app: &mut VectorcraftApp, p: &Value) -> Result<Value, String> {
let (text, stem) = match p.get("data") {
Some(Value::String(data)) => {
+1 -3
View File
@@ -522,9 +522,7 @@ mod tests {
fn actions_panel_play_records_pathfinder_step() {
let mut app = two_squares();
click_button(&mut app, "Intersect");
app.ui.action_sets[0]
.actions
.push(crate::panels::actions::Action { name: "Unite".into(), steps: vec![("object.pathfinder.unite".into(), json!({}))] });
app.ui.action_sets[0].actions.push(crate::panels::actions::Action::new("Unite", vec![("object.pathfinder.unite".into(), json!({}))]));
let idx = app.ui.action_sets[0].actions.len() - 1;
select_two_squares(&mut app, 110.0);
crate::panels::actions::play(&mut app, 0, idx).unwrap();
+29
View File
@@ -1445,6 +1445,35 @@ mod tests {
assert!(import_json(&json!({})).is_err());
}
/// The dialog's Import… leaves an action its function key when the imported set gives the key
/// to a command, through both Cancel and OK.
#[test]
fn importing_into_the_dialog_preserves_action_keys_on_ok() {
use crate::panels::actions::{Action, ActionSet, FunctionKey};
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
let f15 = FunctionKey { key: 15, cmd: false, shift: false };
let mut nudge = Action::new("Nudge", vec![]);
nudge.key = Some(f15);
app.ui.action_sets.push(ActionSet::new("Mine", vec![nudge]));
let mut ov = Overrides::new();
crate::keymap::set_override(&mut ov, "edit.duplicate", "F15");
let bytes = serde_json::to_vec(&export_json("Imported", &ov)).unwrap();
app.services.pick_open = Some(Box::new(|_: &crate::FilePick| Some("/sets/Imported.json".to_string())));
app.services.read = Some(Box::new(move |_: &str| Ok(bytes.clone())));
let key = |app: &VectorcraftApp| app.ui.action_sets.last().and_then(|s| s.actions.first()).and_then(|a| a.key);
open(&mut app);
import_into_dialog(&mut app);
assert_eq!(key(&app), Some(f15), "the import alone keeps the action's key");
assert!(app.ui.shortcut_overrides.is_empty(), "the import is only in the dialog");
app.ui.dialog = None;
assert_eq!(key(&app), Some(f15), "Cancel keeps the action's key");
open(&mut app);
import_into_dialog(&mut app);
assert_eq!(key(&app), Some(f15));
confirm(&mut app).unwrap();
assert_eq!(key(&app), Some(f15), "OK keeps the action's function key");
}
#[test]
fn presets_are_the_defaults() {
for p in PRESETS {
+9 -2
View File
@@ -154,14 +154,18 @@ fn runs_a_command(i: &egui::InputState, key: Key, cmd_only: bool) -> bool {
/// `key` and `code` are the browser's names for the character typed and the key's position, which
/// egui reads with [`Key::from_name`]; `modifiers` as egui reports them. The press is matched as
/// the dispatcher matches it ([`dispatch`]) on a layout about which nothing is known: what typing
/// has shown of the layout is left out, and so are double presses.
/// has shown of the layout is left out, and so are double presses. An action's function key runs
/// a shortcut too.
pub fn runs_a_shortcut(key: &str, code: &str, modifiers: Modifiers) -> bool {
let physical_key = Key::from_name(code);
let Some(key) = Key::from_name(key).or(physical_key) else { return false };
let press = egui::Event::Key { key, physical_key, pressed: true, repeat: false, modifiers };
let Some(input) = craft_keymap::KeyInput::from_egui(&press, crate::keymap::platform()) else { return false };
let mirror = crate::shortcut_editor::current();
craft_keymap::Layout::default().candidates(&input).iter().any(|c| mirror.keymap.lookup(c, false, &Active::NONE) != craft_keymap::Lookup::None)
craft_keymap::Layout::default()
.candidates(&input)
.iter()
.any(|c| mirror.keymap.lookup(c, false, &Active::NONE) != craft_keymap::Lookup::None || crate::panels::actions::plays_an_action(c))
}
/// Process one frame's events against the keymap at most once per context, viewport and frame, so
@@ -338,6 +342,8 @@ pub fn handle(app: &mut VectorcraftApp, ctx: &egui::Context) {
if claimed_tool_keys(app, ctx, view, rows_keys) {
return;
}
// An action's function key plays the action, also when a command has the same shortcut.
crate::panels::actions::play_function_key(app, ctx);
// Command, panel and tool shortcuts. A bound shifted punctuation chord uses its key press;
// other text keys use the typed character below.
let row_key = |chord: &craft_keymap::Chord| {
@@ -487,6 +493,7 @@ fn type_tool_input(app: &mut VectorcraftApp, ctx: &egui::Context, composing: boo
})
});
}
crate::panels::actions::play_function_key(app, ctx);
// Editing keys with modifiers and the clipboard (Cmd+A is Select All's, below: the text).
crate::panels::character::route_type_input(app, ctx);
// Enter was already delivered above as ToolKey::Enter (newline). Only chords with the
+6
View File
@@ -491,6 +491,11 @@ pub struct UiState {
/// Recording in progress: (set index, action name, journal length when recording started).
#[serde(skip)]
pub recording: Option<(usize, String, usize)>,
/// The id of the action New Action made for the recording in progress
/// ([`crate::panels::actions::Action::id`]): Stop gives it the recorded steps. None when Stop
/// adds a new action, as after Begin Recording.
#[serde(skip)]
pub recording_into: Option<u64>,
/// Keyboard shortcut overrides: command id, `tool:<id>` or `panel:<id>` → chord ("" = none),
/// stored in the form every earlier version reads.
#[serde(default, with = "crate::keymap::stored")]
@@ -961,6 +966,7 @@ impl Default for UiState {
action_set: None,
action_sets_selected: vec![],
recording: None,
recording_into: None,
shortcut_overrides: Default::default(),
shortcut_set: default_shortcut_set(),
workspace: default_workspace(),
+26 -3
View File
@@ -1757,9 +1757,32 @@ already walks Image Trace. Short agent entry points:
refused, and no set is added. The Actions panel menu's Save Actions… and Load Actions… run these; Load Actions… is
disabled where there is no open dialog (the web).
- Actions: `ui.action.rename {set, action, name}` renames the Actions panel's action at `action` in set `set` (0 is
the top set) to `name` with spaces trimmed from both ends, keeps its steps, and returns `{name}`. An index past the
last set or action, or an empty name, is an error, and then nothing is renamed. The panel menu's Action Options…
runs this for the selected action.
the top set) to `name` with spaces trimmed from both ends, keeps its steps, function key and color, and returns
`{name}`. An index past the last set or action, or an empty name, is an error, and then nothing is renamed.
- Actions: `ui.action.new {set, name, key?, cmd?, shift?, color?}` adds an action named `name` (spaces
trimmed) after the last action of set `set` (0 is the top set), starts recording into it and returns
`{set, action}`; Stop Playing/Recording (`ui.action.stop`) ends the recording. `key` 1 to 15 is the function key F1 to F15 that plays the
action (0 or null for none), with `cmd` (Ctrl, Command on macOS) and `shift`. `color` is its Button Mode color
(`red`, `yellow`, `green`, `blue` or `violet`; null or `""` for none), which the panel does not show. Action function
keys take priority over command shortcuts and preserve the command's binding. On Windows F1, Ctrl+F4 and Ctrl+F6
cannot be used. While an action is recording, and for an index past the last set,
an empty name, or a key or color that is not one of these, it is an error and nothing is added. The panel's Create
New Action button and menu's New Action… open the `actionNew` dialog, whose Record runs this.
- Actions: `ui.action.options {set, action, name?, key?, cmd?, shift?, color?}` changes the action at
`action` in set `set` and keeps its steps: `name` renames it, `key` with `cmd` and `shift` sets its function key,
and `color` its Button Mode color, as `ui.action.new` takes them; a param left out keeps what the action has, and
`cmd` or `shift` alone changes that modifier of its key. It
returns `{name, key, color}`. The panel menu's Action Options… runs this for the selected action. A function key
plays its action from the keyboard; like command shortcuts, it does nothing while a dialog, the command palette or
a text field has the keyboard, or while a tool is busy. Editing command shortcuts (`shortcuts.set`, Keyboard Shortcuts), loading preferences and
`ui.actionSet.load` preserve action function keys. When several actions have the same key, the first in panel order
plays. A stored key reserved on the current platform does not play an action.
- Actions: `ui.action.play {action, set?}` plays the action named `action` as one undoable batch; `set` names the set
to look in (default: every set), and a `set` that is not a string is an error. A name that no action has, or that
more than one action in the sets looked in has, is an error, and then nothing plays.
- Actions: `ui.action.stop {}` ends the recording in progress and keeps its steps, in the action `ui.action.new` made
for it, else in a new action after the last action of its set, and returns `{stopped}`. With nothing recording it
changes nothing. The panel's Stop Playing/Recording button runs this.
- Action sets: `ui.actionSet.delete {sets?: [index], ids?: [id]}` deletes the Actions panel's sets at these indexes
(0 is the top set) with their actions, by default the current set, and returns `{deleted}`. An index past the last
set is an error, and then no set is deleted. `ids` holds the panel's own set ids, which its question passes: the
+2 -1
View File
@@ -562,7 +562,8 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- Variables: Lock Variables (`variable.lock`, in the Variables panel's bottom bar and menu) stops variables from being defined, deleted or renamed until they are unlocked, while objects can still be bound and unbound and data sets still change and apply; the lock is saved with the document.
- Batch…: Override Save and Override Export name each file with the extension of the format the step writes, however the step spells the format (`.svg` and `SVG` give `.svg`, `png8` gives `.png`), in `action.batch`.
- Actions panel menu: Save Actions… writes the current action set with all its actions to a file, and Load Actions… adds the set from such a file to the panel ([Manage a set of actions](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/manage-a-set-of-actions.html): "Select Save Actions from the Actions panel menu", "You can save only the entire contents of a set", "Select Load Actions from the Actions panel menu"; `ui.actionSet.save`, `ui.actionSet.load`). The file is VectorCraft's own action set file (`.vcactions`); a loaded set named like one in the panel gets the next free number.
- Actions panel: the panel menu's Action Options… renames the selected action and keeps its steps ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html): "Opens a dialog to rename or assign function keys/colors to the action"; `ui.action.rename`). The dialog has the name only; the function key and color are not there yet.
- Actions panel: the panel menu's Action Options… renames the selected action and keeps its steps ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html): the menu item opens a dialog that renames the action or gives it a function key and color; `ui.action.options`). It also sets the action's function key and color.
- Actions panel: Create New Action (bottom bar) and the panel menu's New Action… ask for the new action's name, set, function key and color, and Record adds the action and starts recording into it ([Create new actions](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/record-actions.html): the New Action dialog takes the action's name and the set it goes in; `ui.action.new`, `ui.action.play`). The function key (F1 to F15, with Ctrl or Command and Shift) plays the action. VectorCraft's own rules, which the page does not cover: a key another action or a command has is refused until Replace is ticked, which takes it from them; a shortcut given to a command later takes the key from the action; a copied action, and a loaded action whose key is taken, have no key; New Action does not open while an action is recording. The color is kept with the action for Button Mode, which VectorCraft does not have yet.
- Actions panel (record/playback, persisted), generic parameter dialogs for every "…" command.
- Actions panel: the current set is kept with the UI preferences, so after a restart a recording goes into the set that was current, not into the first set. With no set current, Begin Recording records into the first set and makes it current.
- Actions panel: Delete Selection deletes the selected action set with its actions and keeps the other sets ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html): "Removes the selected action, command, or action set from the panel"; `ui.actionSet.delete`). VectorCraft's own rules, which the overview does not cover: deleting a set asks first, Shift-click on a set's name selects a range of sets to delete together, the panel menu's Delete does the same, and Default Actions and the last set can be deleted. Undo does not bring a deleted set back.
+3 -2
View File
@@ -303,9 +303,10 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
| Image Trace panel: the Preview checkbox before Trace chooses whether a setting change traces the selected Image Trace object again at once | done | Per the public documentation, Preview shows the result of the current settings and Trace traces with them (<https://web.archive.org/web/20250831090623/https://helpx.adobe.com/illustrator/using/image-trace.html>). Preview is on by default and kept with the UI preferences; Reset to Default leaves it. Off, changes wait in the panel until Trace applies them as one undo step, or until Preview is turned on again. Changes stay with the object they were made for while another object is selected, and come back when it is selected again. `imageTrace.preview {on?}`, `ui.set {imageTracePreview}`; `panels/image_trace.rs` headless tests (`with_preview_off_a_slider_change_waits_for_trace`, `turning_preview_on_traces_the_changes_that_waited`, `preview_turned_on_with_nothing_selected_traces_when_the_object_is_selected_again`, `settings_that_wait_stay_with_their_object`, `settings_that_wait_come_back_when_their_object_is_selected_again`, `settings_that_wait_are_dropped_when_their_object_changed_since`, `preview_is_kept_with_the_preferences_and_reset_to_default_leaves_it`) |
| Toolbar without group labels by default, one or two columns; All Tools drawer by flyout group with shortcuts, its menu (Reset, Basic, Advanced) and Show section | done | #1751; a preference brings the labels back; `toolbar.show` sets the Fill/Stroke, Coloring, Draw Mode and Screen Mode controls |
| Actions panel: ≡ › Save Actions… saves the current set with all its actions to a file and ≡ › Load Actions… adds a saved set ([Manage a set of actions](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/manage-a-set-of-actions.html)) | partial | `ui.actionSet.save`, `ui.actionSet.load`; `panels/actions.rs` tests. The file is VectorCraft's own `.vcactions` JSON; the reference app's `.aia` files and Reset, Clear and Replace Actions remain |
| Actions panel: ≡ › Action Options… renames the selected action ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html): "Opens a dialog to rename or assign function keys/colors to the action") | partial | `ui.action.rename`; `panels/actions.rs` tests (part of #1629). The dialog has the name only: the function key and color remain |
| Actions panel: ≡ › Action Options… renames the selected action and sets its function key and color ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html): "Opens a dialog to rename or assign function keys/colors to the action") | partial | `ui.action.options`; `panels/actions.rs` tests (part of #1629). The color shows nowhere until Button Mode exists |
| Actions panel: a clicked action stays selected for Play Current Selection and Delete Selection | partial | #1853 (part of #1629); editing actions and action shortcuts remain |
| Actions panel: Create New Set (bottom bar, ≡ › New Set…) names a new set and Set Options… renames the current one; a click on a set's name makes it current and a recording goes into the current set ([helpx: Automation with actions](https://helpx.adobe.com/illustrator/using/automation-actions.html)); the current set is kept with the UI preferences, and with no set current a recording goes into the first set, which becomes current | partial | #3712; the New Action dialog (name, set menu, shortcut, colour) and dragging actions between sets remain |
| Actions panel: Create New Set (bottom bar, ≡ › New Set…) names a new set and Set Options… renames the current one; a click on a set's name makes it current and a recording goes into the current set ([helpx: Automation with actions](https://helpx.adobe.com/illustrator/using/automation-actions.html)); the current set is kept with the UI preferences, and with no set current a recording goes into the first set, which becomes current | partial | #3712; dragging actions between sets remains |
| Actions panel: Create New Action (bottom bar, ≡ › New Action…) asks for the name, set, function key and color, and Record adds the action and records into it ([Create new actions](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/record-actions.html)) | partial | `ui.action.new`, `ui.action.play`; `panels/actions.rs` tests. A function key plays its action; a taken key needs Replace, and a shortcut given to a command later takes the key from the action. Button Mode, which shows the color, remains |
| Actions panel: Delete Selection (bottom bar) deletes the selected set with its actions and keeps the other sets ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html): "Removes the selected action, command, or action set from the panel") | partial | `ui.actionSet.delete`; `panels/actions.rs` tests. VectorCraft's own rules, which the overview does not cover: deleting a set asks first (a selected action is still deleted at once), Shift-click on a set's name selects a range of sets, ≡ › Delete does the same as the button, and Default Actions and the last set can be deleted. Undo does not restore a deleted set, and recorded commands cannot be selected or deleted |
| Actions panel: ≡ › Duplicate copies the selected action or set ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html): "Makes a copy of the selected action or set.") | partial | `ui.actionSet.duplicate`; `panels/actions.rs` tests. VectorCraft's own rules, which the overview does not cover: the copy goes right after the original, is named after it with " copy" added and is selected, and a copied set holds copies of all its actions. Undo does not remove the copy, and recorded commands cannot be duplicated |
| Properties panel per context (every selection type's Quick Actions) | partial | one clip group: Edit Clipping Path and Edit Contents, at the top of the panel rather than in Quick Actions (G1); the overview's additional controls ([Properties panel overview](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/properties-panel-overview.html)): Blend Options (one blend selected, with any tool, #4817) and Merge Live Paint (a Live Paint group with more) in Quick Actions, the Width Profile list (Width tool or a variable-width stroke) and an applied effect's Delete icon in Appearance, Corner and Corner Radius for corners selected with Direct Selection; Variable Font was already there |