variables: review fixes for the panel, dialogs and translations
- Dataset and variable names are the user's: the panel's Data Set dropdown and
the dialogs' name dropdowns show them as they are instead of translating
them; the dialog's Kind dropdown shows translated kind names.
- Choosing the empty option in a dialog dropdown picked the first name.
- The panel reads the art once per frame for every row's italics, the dialog
no longer clones the document's variables every frame, and slices are
matched instead of indexed.
- "No document" and "Define a variable first" go through tl!, and the dialog
headings Variable Options / Edit Data Set, Text and Visibility have rows in
every complete catalog; the unused "{name} · {kind} · {count}" row is gone.
- German rows for every Variables string (the catalog predates this branch).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b3fa281282
commit
500e19680d
|
|
@ -21,6 +21,11 @@ pub const KIND: &str = "variables";
|
|||
/// The kinds a variable can have, as `variable.define` names them.
|
||||
const KINDS: [&str; 2] = ["text", "visibility"];
|
||||
|
||||
/// What the dialog shows for each of [`KINDS`].
|
||||
fn kind_labels() -> [&'static str; 2] {
|
||||
[tl!("Text"), tl!("Visibility")]
|
||||
}
|
||||
|
||||
pub(super) const SPEC: DialogSpec =
|
||||
DialogSpec { heading: |d| tl!(&d.str("__label")).to_string(), body, confirm, min_width: 380.0, ..DialogSpec::FORM };
|
||||
|
||||
|
|
@ -96,7 +101,7 @@ pub fn open(app: &mut VectorcraftApp, id: &str, preselect: Option<&str>) -> bool
|
|||
app.status(if key == "variable" { tl!("no variable to rename").to_string() } else { tl!("no data set to rename").to_string() });
|
||||
return true;
|
||||
}
|
||||
fields.insert(key.into(), json!(preselect.filter(|p| names.contains(p)).unwrap_or(names[0])));
|
||||
fields.insert(key.into(), json!(preselect.filter(|p| names.contains(p)).or(names.first().copied()).unwrap_or_default()));
|
||||
fields.insert("newName".into(), json!(""));
|
||||
}
|
||||
}
|
||||
|
|
@ -136,10 +141,10 @@ fn value_key(name: &str) -> String {
|
|||
fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
let Some(st) = app.session.active() else {
|
||||
widgets::dim_label(ui, "No document");
|
||||
widgets::dim_label(ui, tl!("No document"));
|
||||
return false;
|
||||
};
|
||||
let vars = st.doc.variables.clone();
|
||||
let vars = &st.doc.variables;
|
||||
let variable_names: Vec<&str> = vars.variables.iter().map(|v| v.name.as_str()).collect();
|
||||
let dataset_names: Vec<&str> = vars.datasets.iter().map(|x| x.name.as_str()).collect();
|
||||
egui::Grid::new("variables-grid").num_columns(2).spacing([12.0, 8.0]).show(ui, |ui| {
|
||||
|
|
@ -150,7 +155,12 @@ fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
|||
text(ui, d, "name", 220.0);
|
||||
ui.end_row();
|
||||
label(ui, tl!("Kind"));
|
||||
dropdown(ui, d, "kind", &KINDS, 220.0);
|
||||
// The kinds by their translated names; the field keeps the command's own word.
|
||||
let labels = kind_labels();
|
||||
let shown = KINDS.iter().position(|k| *k == d.str("kind")).and_then(|i| labels.get(i)).copied().unwrap_or_default();
|
||||
if let Some(kind) = widgets::dropdown_names(ui, ("variables-dd", "kind"), shown, &labels, 220.0).and_then(|i| KINDS.get(i)) {
|
||||
d.fields.insert("kind".into(), json!(kind));
|
||||
}
|
||||
ui.end_row();
|
||||
}
|
||||
"variable.bind" => {
|
||||
|
|
@ -182,7 +192,7 @@ fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
|||
text(ui, d, "name", 220.0);
|
||||
ui.end_row();
|
||||
if vars.variables.is_empty() {
|
||||
widgets::dim_label(ui, "Define a variable first");
|
||||
widgets::dim_label(ui, tl!("Define a variable first"));
|
||||
ui.end_row();
|
||||
return;
|
||||
}
|
||||
|
|
@ -223,16 +233,18 @@ fn checkbox(ui: &mut egui::Ui, d: &mut Dialog, key: &str) -> egui::Response {
|
|||
r
|
||||
}
|
||||
|
||||
/// A dropdown over `options` for `key`, written back as it changes. The empty option is first
|
||||
/// so a fresh dialog can still be filled in; a name that is no longer offered reads as empty
|
||||
/// rather than being silently swapped for another one.
|
||||
/// A dropdown over the document's names `options` (shown as they are, never translated) for
|
||||
/// `key`, written back as it changes. The empty option is first so a fresh dialog can still be
|
||||
/// filled in; a name that is no longer offered reads as empty rather than being silently
|
||||
/// swapped for another one.
|
||||
fn dropdown(ui: &mut egui::Ui, d: &mut Dialog, key: &str, options: &[&str], width: f32) {
|
||||
let cur = d.str(key);
|
||||
let mut labels: Vec<&str> = vec![""];
|
||||
labels.extend_from_slice(options);
|
||||
let shown = if cur.is_empty() || options.contains(&cur.as_str()) { cur.as_str() } else { "" };
|
||||
if let Some(i) = widgets::dropdown(ui, ("variables-dd", key), shown, &labels, width) {
|
||||
d.fields.insert(key.into(), json!(options.get(i.saturating_sub(1)).copied().unwrap_or_default()));
|
||||
if let Some(i) = widgets::dropdown_names(ui, ("variables-dd", key), shown, &labels, width) {
|
||||
// The empty option (0) empties the field; the rest are `options`, one along.
|
||||
d.fields.insert(key.into(), json!(i.checked_sub(1).and_then(|i| options.get(i)).copied().unwrap_or_default()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -257,13 +269,15 @@ fn values_of(d: &Dialog, vars: &Variables) -> Value {
|
|||
fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
|
||||
let cmd = d.str("__command");
|
||||
let name = d.str("name");
|
||||
let vars = app.session.active().map(|st| st.doc.variables.clone()).unwrap_or_default();
|
||||
let p = match cmd.as_str() {
|
||||
"variable.define" => json!({"name": name, "kind": d.str("kind")}),
|
||||
"variable.bind" => json!({"variable": d.str("variable")}),
|
||||
"variable.rename" => json!({"name": d.str("variable"), "newName": d.str("newName")}),
|
||||
"dataset.rename" => json!({"name": name, "newName": d.str("newName")}),
|
||||
"dataset.new" | "dataset.set" => json!({"name": name, "values": values_of(d, &vars)}),
|
||||
"dataset.new" | "dataset.set" => {
|
||||
let values = app.session.active().map(|st| values_of(d, &st.doc.variables)).unwrap_or_else(|| json!({}));
|
||||
json!({"name": name, "values": values})
|
||||
}
|
||||
"dataset.select" => json!({"name": name}),
|
||||
_ => json!({}),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3954,3 +3954,46 @@ theme Appearance Erscheinungsbild
|
|||
Frosted Mattiert
|
||||
Tiny Lens Kleine Linsen
|
||||
Canvas Leinwand
|
||||
Highlight Variable Variable hervorheben
|
||||
New Variable Neue Variable
|
||||
Delete Variable Variable löschen
|
||||
List Variables Variablen auflisten
|
||||
Bind Variable Variable binden
|
||||
Unbind Variable Variable lösen
|
||||
New Data Set Neuer Datensatz
|
||||
Delete Data Set Datensatz löschen
|
||||
List Data Sets Datensätze auflisten
|
||||
Select Data Set Datensatz auswählen
|
||||
Next Data Set Nächster Datensatz
|
||||
Previous Data Set Vorheriger Datensatz
|
||||
Data Sets Datensätze
|
||||
New Variable… Neue Variable…
|
||||
Bind Variable… Variable binden…
|
||||
New Data Set… Neuer Datensatz…
|
||||
Edit Data Set… Datensatz bearbeiten…
|
||||
Select Data Set… Datensatz auswählen…
|
||||
Variables Panel Bedienfeld „Variablen“
|
||||
Data Set Datensatz
|
||||
Kind Art
|
||||
Variable Variable
|
||||
no document kein Dokument
|
||||
no data set to edit kein Datensatz zum Bearbeiten
|
||||
Make Text Dynamic Text dynamisch machen
|
||||
Make Visibility Dynamic Sichtbarkeit dynamisch machen
|
||||
Capture Data Set Datensatz erfassen
|
||||
Update Data Set Datensatz aktualisieren
|
||||
Rename Data Set… Datensatz umbenennen…
|
||||
Variable Options… Variablenoptionen…
|
||||
Select Bound Object Gebundenes Objekt auswählen
|
||||
Select All Bound Objects Alle gebundenen Objekte auswählen
|
||||
Multiple objects Mehrere Objekte
|
||||
New Name Neuer Name
|
||||
no variable to rename keine Variable zum Umbenennen
|
||||
no data set to rename kein Datensatz zum Umbenennen
|
||||
Rename Data Set Datensatz umbenennen
|
||||
Rename Variable Variable umbenennen
|
||||
Variable Options Variablenoptionen
|
||||
Edit Data Set Datensatz bearbeiten
|
||||
Define a variable first Definieren Sie zuerst eine Variable
|
||||
Text Text
|
||||
Visibility Sichtbarkeit
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3079,7 +3079,6 @@
|
|||
Variable Variable
|
||||
no document no hay documento
|
||||
no data set to edit no hay ningún conjunto de datos que editar
|
||||
{name} · {kind} · {count} {name} · {kind} · {count}
|
||||
Make Text Dynamic Hacer texto dinámico
|
||||
Make Visibility Dynamic Hacer visible dinámico
|
||||
Capture Data Set Capturar conjunto de datos
|
||||
|
|
@ -4036,3 +4035,8 @@ axis Both Ambos
|
|||
Tiny Lens Lente pequeña
|
||||
Rename Data Set Renombrar conjunto de datos
|
||||
Rename Variable Renombrar variable
|
||||
Variable Options Opciones de variable
|
||||
Edit Data Set Editar conjunto de datos
|
||||
Define a variable first Defina primero una variable
|
||||
Text Texto
|
||||
Visibility Visibilidad
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3076,7 +3076,6 @@
|
|||
Variable Variable
|
||||
no document aucun document
|
||||
no data set to edit aucun jeu de données à modifier
|
||||
{name} · {kind} · {count} {name} · {kind} · {count}
|
||||
Make Text Dynamic Rendre le texte dynamique
|
||||
Make Visibility Dynamic Rendre la visibilité dynamique
|
||||
Capture Data Set Capturer le jeu de données
|
||||
|
|
@ -4048,3 +4047,8 @@ effect Soft Doux
|
|||
Tiny Lens Petites lentilles
|
||||
Rename Data Set Renommer le jeu de données
|
||||
Rename Variable Renommer la variable
|
||||
Variable Options Options de variable
|
||||
Edit Data Set Modifier le jeu de données
|
||||
Define a variable first Définissez d’abord une variable
|
||||
Text Texte
|
||||
Visibility Visibilité
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3079,7 +3079,6 @@
|
|||
Variable Variabile
|
||||
no document nessun documento
|
||||
no data set to edit nessun set di dati da modificare
|
||||
{name} · {kind} · {count} {name} · {kind} · {count}
|
||||
Make Text Dynamic Rendi testo dinamico
|
||||
Make Visibility Dynamic Rendi visibilità dinamica
|
||||
Capture Data Set Cattura set di dati
|
||||
|
|
@ -4038,3 +4037,8 @@ effect Regular Normale
|
|||
Tiny Lens Lente piccola
|
||||
Rename Data Set Rinomina set di dati
|
||||
Rename Variable Rinomina variabile
|
||||
Variable Options Opzioni variabile
|
||||
Edit Data Set Modifica set di dati
|
||||
Define a variable first Definisci prima una variabile
|
||||
Text Testo
|
||||
Visibility Visibilità
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -592,7 +592,6 @@
|
|||
Variable 変数
|
||||
no document ドキュメントがありません
|
||||
no data set to edit 編集するデータセットがありません
|
||||
{name} · {kind} · {count} {name} · {kind} · {count} 件
|
||||
Make Text Dynamic テキストを動的にする
|
||||
Make Visibility Dynamic 表示を動的にする
|
||||
Capture Data Set データセットを取得
|
||||
|
|
@ -4031,3 +4030,8 @@ effect Vertical 垂直
|
|||
Frosted すりガラス
|
||||
Tiny Lens 小さなレンズ
|
||||
Rename Data Set データセットの名前を変更
|
||||
Variable Options 変数のオプション
|
||||
Edit Data Set データセットを編集
|
||||
Define a variable first 先に変数を定義してください
|
||||
Text テキスト
|
||||
Visibility 表示状態
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3075,7 +3075,6 @@
|
|||
Variable Переменная
|
||||
no document нет документа
|
||||
no data set to edit нет набора данных для изменения
|
||||
{name} · {kind} · {count} {name} · {kind} · {count}
|
||||
Make Text Dynamic Сделать текст динамическим
|
||||
Make Visibility Dynamic Сделать видимость динамической
|
||||
Capture Data Set Записать набор данных
|
||||
|
|
@ -4034,3 +4033,8 @@ axis Both Оба
|
|||
Tiny Lens Мелкие линзы
|
||||
Rename Data Set Переименовать набор данных
|
||||
Rename Variable Переименовать переменную
|
||||
Variable Options Параметры переменной
|
||||
Edit Data Set Изменить набор данных
|
||||
Define a variable first Сначала определите переменную
|
||||
Text Текст
|
||||
Visibility Видимость
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3071,7 +3071,6 @@
|
|||
Variable Змінна
|
||||
no document немає документа
|
||||
no data set to edit немає набору даних для зміни
|
||||
{name} · {kind} · {count} {name} · {kind} · {count}
|
||||
Make Text Dynamic Зробити текст динамічним
|
||||
Make Visibility Dynamic Зробити видимість динамічною
|
||||
Capture Data Set Записати набір даних
|
||||
|
|
@ -4019,3 +4018,8 @@ axis Both Обидві
|
|||
Tiny Lens Дрібні лінзи
|
||||
Rename Data Set Перейменувати набір даних
|
||||
Rename Variable Перейменувати змінну
|
||||
Variable Options Параметри змінної
|
||||
Edit Data Set Змінити набір даних
|
||||
Define a variable first Спочатку визначте змінну
|
||||
Text Текст
|
||||
Visibility Видимість
|
||||
|
|
|
|||
|
Can't render this file because it has a wrong number of fields in line 13.
|
|
|
@ -2970,7 +2970,6 @@
|
|||
Variable 变量
|
||||
no document 没有文档
|
||||
no data set to edit 没有可编辑的数据集
|
||||
{name} · {kind} · {count} {name} · {kind} · {count}
|
||||
Make Text Dynamic 使文本动态化
|
||||
Make Visibility Dynamic 使可见性动态化
|
||||
Capture Data Set 捕获数据集
|
||||
|
|
@ -3667,3 +3666,8 @@ effect Vertical 垂直
|
|||
Tiny Lens 小镜头
|
||||
Rename Data Set 重命名数据集
|
||||
Rename Variable 重命名变量
|
||||
Variable Options 变量选项
|
||||
Edit Data Set 编辑数据集
|
||||
Define a variable first 请先定义一个变量
|
||||
Text 文本
|
||||
Visibility 可见性
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
|
|
@ -3062,7 +3062,6 @@
|
|||
Variable 變數
|
||||
no document 沒有文件
|
||||
no data set to edit 沒有可編輯的資料集
|
||||
{name} · {kind} · {count} {name} · {kind} · {count}
|
||||
Make Text Dynamic 使文字動態化
|
||||
Make Visibility Dynamic 使可見性動態化
|
||||
Capture Data Set 擷取資料集
|
||||
|
|
@ -3448,3 +3447,8 @@ effect Soft 柔和
|
|||
Tiny Lens 小鏡頭
|
||||
Rename Data Set 重新命名資料集
|
||||
Rename Variable 重新命名變數
|
||||
Variable Options 變數選項
|
||||
Edit Data Set 編輯資料集
|
||||
Define a variable first 請先定義一個變數
|
||||
Text 文字
|
||||
Visibility 可見性
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
|
|
@ -64,18 +64,14 @@ pub(crate) fn select_bound_object(app: &mut VectorcraftApp) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Delete Variable: the highlighted variable only; the rest of the rows stay.
|
||||
/// Delete Variable: the highlighted variable only (the command's default); the rest stay.
|
||||
pub(crate) fn delete_highlighted(app: &mut VectorcraftApp) {
|
||||
if let Some(name) = app.session.active().and_then(highlighted_row) {
|
||||
app.run("variable.delete", json!({"names": [name]})).ok();
|
||||
}
|
||||
app.run("variable.delete", json!({})).ok();
|
||||
}
|
||||
|
||||
/// Delete Data Set: the current one only; the rest of the rows stay.
|
||||
/// Delete Data Set: the current one only (the command's default); the rest of the rows stay.
|
||||
pub(crate) fn delete_active_dataset(app: &mut VectorcraftApp) {
|
||||
if let Some(name) = app.session.active().and_then(|st| st.doc.variables.active_dataset.clone()) {
|
||||
app.run("dataset.delete", json!({"names": [name]})).ok();
|
||||
}
|
||||
app.run("dataset.delete", json!({})).ok();
|
||||
}
|
||||
|
||||
pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
|
|
@ -91,14 +87,16 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
|||
.iter()
|
||||
.map(|v| {
|
||||
let bound: Vec<u64> = st.doc.variables.objects_of(&v.name).iter().map(|i| i.0).collect();
|
||||
let object = match bound.len() {
|
||||
0 => String::new(),
|
||||
1 => st.doc.node(NodeId(bound[0])).map(|n| n.display_name()).unwrap_or_default(),
|
||||
let object = match bound.as_slice() {
|
||||
[] => String::new(),
|
||||
[one] => st.doc.node(NodeId(*one)).map(|n| n.display_name()).unwrap_or_default(),
|
||||
_ => tl!("Multiple objects").to_string(),
|
||||
};
|
||||
VarRow { name: v.name.clone(), kind: v.kind, bound, object }
|
||||
})
|
||||
.collect();
|
||||
// What the art holds now, read once for every row's drift check.
|
||||
let current = st.doc.captured_values();
|
||||
let sets: Vec<SetRow> = st
|
||||
.doc
|
||||
.variables
|
||||
|
|
@ -108,7 +106,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
|||
name: d.name.clone(),
|
||||
values: d.values.len(),
|
||||
active: st.doc.variables.active_dataset.as_deref() == Some(d.name.as_str()),
|
||||
matches: st.doc.matches_dataset(&d.name),
|
||||
matches: d.matches(¤t),
|
||||
})
|
||||
.collect();
|
||||
let active = sets.iter().find(|s| s.active);
|
||||
|
|
@ -118,18 +116,18 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
|||
// Unbind needs a bound object under the selection, not just any selection.
|
||||
let selection_bound = selected.iter().any(|id| st.doc.variables.bindings.contains_key(&NodeId(*id)));
|
||||
// Make Text Dynamic needs exactly one type object: a text variable only drives type.
|
||||
let single_type = selected.len() == 1 && st.doc.node(NodeId(selected[0])).is_some_and(|n| matches!(n.kind, NodeKind::Text(_)));
|
||||
let single_type = matches!(selected.as_slice(), [one] if st.doc.node(NodeId(*one)).is_some_and(|n| matches!(n.kind, NodeKind::Text(_))));
|
||||
|
||||
// The current data set across the top: its name, and the arrows that step through them.
|
||||
ui.horizontal(|ui| {
|
||||
widgets::field_label(ui, tl!("Data Set"));
|
||||
let names: Vec<&str> = sets.iter().map(|s| s.name.as_str()).collect();
|
||||
let current = active.map(|s| s.name.as_str()).unwrap_or("");
|
||||
let picked = widgets::dropdown(ui, "variables-active", current, &names, 160.0);
|
||||
if let Some(i) = picked
|
||||
&& names.get(i).is_some_and(|n| *n != current)
|
||||
let picked = widgets::dropdown_names(ui, "variables-active", current, &names, 160.0);
|
||||
if let Some(name) = picked.and_then(|i| names.get(i))
|
||||
&& *name != current
|
||||
{
|
||||
app.run("dataset.select", json!({"name": names[i]})).ok();
|
||||
app.run("dataset.select", json!({"name": name})).ok();
|
||||
}
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
let has = !sets.is_empty();
|
||||
|
|
|
|||
Loading…
Reference in New Issue