Select: select.color picks objects by fill and stroke colour, no object needed

Scripts had to know an object id before they could select art by colour
(select.same.* and select.magicWand start from one). select.color
{fill?, stroke?} takes colours as paint.setFill does and selects the
objects whose fill and stroke read as them in #rrggbb, as
document.inspect reports colours, with Select > Same's selection rules.

The label is translated in each of the 23 catalogs, which
complete_languages_translate_every_menu_string requires.
This commit is contained in:
MortenHusted
2026-10-18 23:50:57 +07:00
committed by bflatastic
parent 09a6fbe470
commit d25289a3be
25 changed files with 103 additions and 0 deletions
+25
View File
@@ -89,6 +89,15 @@ pub fn specs() -> Vec<CommandSpec> {
has_doc,
anchors_many
),
cmd!(
"select.color",
"Select by Color",
[],
None,
"{fill?: colour, stroke?: colour (as paint.setFill's color; at least one)} select the objects whose fill (and stroke) reads as that colour in #rrggbb, as document.inspect reports colours, whatever its swatch or tint; with both, the objects that match both. No object needs to be selected first; Select > Reselect repeats it → {count}",
has_doc,
select_color
),
cmd!(
"select.same.fillColor",
"Fill Color",
@@ -528,6 +537,22 @@ fn stroke_weight(n: &Node) -> f64 {
if paint.is_none() { 0.0 } else { width }
}
/// Select by Color: the objects whose fill and stroke read as the colours given, compared as the
/// `#rrggbb` `document.inspect` reports, so a script can pick art by colour without an object id.
fn select_color(s: &mut Session, p: &Value) -> Result<Value> {
const C: &str = "select.color";
let hex = |key: &str| match p.get(key).filter(|v| !v.is_null()) {
None => Ok(None),
Some(v) => color_value(v).map(|c| Some(c.to_hex())).ok_or_else(|| bad(C, format!("`{key}`: not a colour: {v}"))),
};
let (fill, stroke) = (hex("fill")?, hex("stroke")?);
if fill.is_none() && stroke.is_none() {
return Err(bad(C, "give `fill`, `stroke` or both"));
}
let reads_as = |paint: Paint, hex: Option<&str>| hex.is_none_or(|h| paint.color().is_some_and(|c| c.to_hex() == h));
select_where(s, C, p, |_, n| !n.is_container() && reads_as(fill_of(n), fill.as_deref()) && reads_as(stroke_of(n).0, stroke.as_deref()))
}
fn same(s: &mut Session, cmd: &str, eq: impl Fn(&Node, &Node) -> bool) -> Result<Value> {
let st = s.doc()?;
let refn = st.selection.objects.first().and_then(|id| st.doc.node(*id)).cloned().ok_or_else(|| bad(cmd, "nothing selected"))?;
+32
View File
@@ -1026,6 +1026,38 @@ fn select_same_paint_reads_type_characters() {
assert_eq!(same(&mut s, t1, "select.same.fillAndStroke"), vec![t1, r]);
}
/// Select by Color needs no object to start from: it matches fills and strokes as
/// `document.inspect` reports them, `#rrggbb`.
#[test]
fn select_color_matches_fill_and_stroke_without_a_selection() {
let mut s = session();
let [a, b, c] = [0.0, 20.0, 40.0].map(|x| rect(&mut s, x, 0.0, 10.0, 10.0));
let t = text(&mut s, "a");
fill(&mut s, a, "#000000");
fill(&mut s, t, "#000000");
// A grey as a PDF stores it reads as #fefefe.
s.execute("paint.setFill", &json!({"ids": [b.0], "color": [0.996, 0.996, 0.996]})).unwrap();
fill(&mut s, c, "#ff0000");
s.execute("paint.setStroke", &json!({"ids": [a.0, c.0], "color": "#0000ff"})).unwrap();
s.execute("select.none", &json!({})).unwrap();
let pick = |s: &mut Session, p: Value| {
s.execute("select.color", &p).unwrap();
let mut v = selected(s);
v.sort();
v
};
assert_eq!(pick(&mut s, json!({"fill": "#000000"})), vec![a, t]);
assert_eq!(pick(&mut s, json!({"fill": "#fefefe"})), vec![b]);
assert_eq!(pick(&mut s, json!({"stroke": "#0000ff"})), vec![a, c]);
assert_eq!(pick(&mut s, json!({"fill": "#000000", "stroke": "#0000ff"})), vec![a]);
// Select > Reselect repeats it.
s.execute("select.none", &json!({})).unwrap();
s.execute("select.reselect", &json!({})).unwrap();
assert_eq!(selected(&s), vec![a]);
assert!(s.execute("select.color", &json!({})).is_err());
assert!(s.execute("select.color", &json!({"fill": "not a colour"})).is_err());
}
#[test]
fn select_direction_handles_selects_all_anchors() {
let mut s = session();
+2
View File
@@ -5170,3 +5170,5 @@ theme Appearance Външен вид
Minimum must not exceed Desired, nor Desired Maximum. Минималната стойност не може да надвишава желаната, нито желаната – максималната.
Justification Подравняване
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them променливите и наборите от данни на файла не бяха прочетени (променливи: {variables}, набори от данни: {data_sets}): панелът „Променливи“ не ги показва
# Select by Color (select.color)
Select by Color Избиране по цвят
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5205,3 +5205,5 @@ mark-style Japanese Japonské
Minimum must not exceed Desired, nor Desired Maximum. Minimum nesmí překročit požadovanou hodnotu ani požadovaná hodnota maximum.
Justification Zarovnání do bloku
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them proměnné a sady dat souboru nebyly načteny (proměnné: {variables}, sady dat: {data_sets}): panel Proměnné je nezobrazuje
# Select by Color (select.color)
Select by Color Vybrat podle barvy
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5188,3 +5188,5 @@ swatch Bright Violet Kraftig violet
Full Justify Lige margener
Minimum must not exceed Desired, nor Desired Maximum. Minimum må ikke overstige Ønsket, og Ønsket ikke Maksimum.
Justification Justering
# Select by Color (select.color)
Select by Color Markér efter farve
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4785,3 +4785,5 @@ effect Soft Weich
Minimum Minimum
Justification Abstände
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them die Variablen und Datensätze der Datei wurden nicht gelesen (Variablen: {variables}, Datensätze: {data_sets}): Das Bedienfeld „Variablen“ listet sie nicht auf
# Select by Color (select.color)
Select by Color Nach Farbe auswählen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5157,3 +5157,5 @@ effect Points Σημεία
Minimum must not exceed Desired, nor Desired Maximum. Το ελάχιστο δεν πρέπει να υπερβαίνει το επιθυμητό, ούτε το επιθυμητό το μέγιστο.
Justification Πλήρης στοίχιση
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them οι μεταβλητές και τα σύνολα δεδομένων του αρχείου δεν διαβάστηκαν (μεταβλητές: {variables}, σύνολα δεδομένων: {data_sets}): ο πίνακας Μεταβλητές δεν τα εμφανίζει
# Select by Color (select.color)
Select by Color Επιλογή βάσει χρώματος
Can't render this file because it contains an unexpected character in line 2006 and column 19.
+2
View File
@@ -5147,3 +5147,5 @@ mark-style Japanese Japonesas
Minimum must not exceed Desired, nor Desired Maximum. El mínimo no puede superar el deseado, ni el deseado el máximo.
Justification Justificación
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them no se leyeron las variables ni los conjuntos de datos del archivo (variables: {variables}, conjuntos de datos: {data_sets}): el panel Variables no los muestra
# Select by Color (select.color)
Select by Color Seleccionar por color
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5169,3 +5169,5 @@ mark-style Japanese Japanilainen
Minimum must not exceed Desired, nor Desired Maximum. Minimi ei saa ylittää haluttua arvoa eikä haluttu arvo maksimia.
Justification Tasaus
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them tiedoston muuttujia ja tietojoukkoja ei luettu (muuttujia: {variables}, tietojoukkoja: {data_sets}): Muuttujat-paneeli ei näytä niitä
# Select by Color (select.color)
Select by Color Valitse värin mukaan
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5204,3 +5204,5 @@ theme Appearance Apparence
Minimum must not exceed Desired, nor Desired Maximum. Le minimum ne doit pas dépasser la valeur optimale, ni la valeur optimale le maximum.
Justification Justification
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them les variables et jeux de données du fichier n’ont pas été lus (variables : {variables}, jeux de données : {data_sets}) : le panneau Variables ne les affiche pas
# Select by Color (select.color)
Select by Color Sélectionner par couleur
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5191,3 +5191,5 @@ imageTrace Outline Körvonal
Minimum must not exceed Desired, nor Desired Maximum. A minimum nem haladhatja meg a kívánt értéket, sem a kívánt érték a maximumot.
Justification Sorkizárás
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them a fájl változói és adatkészletei nem lettek beolvasva (változók: {variables}, adatkészletek: {data_sets}): a Változók panel nem listázza őket
# Select by Color (select.color)
Select by Color Kijelölés szín szerint
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5188,3 +5188,5 @@ swatch Bright Violet Violet cerah
Full Justify Rata Penuh
Minimum must not exceed Desired, nor Desired Maximum. Minimum tidak boleh melebihi Diinginkan, dan Diinginkan tidak boleh melebihi Maksimum.
Justification Justifikasi
# Select by Color (select.color)
Select by Color Pilih berdasarkan warna
Can't render this file because it contains an unexpected character in line 3768 and column 19.
+2
View File
@@ -4819,3 +4819,5 @@ lighting Light Luce
Minimum Minimo
Justification Giustificazione
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them le variabili e i set di dati del file non sono stati letti (variabili: {variables}, set di dati: {data_sets}): il pannello Variabili non li elenca
# Select by Color (select.color)
Select by Color Seleziona per colore
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4859,3 +4859,5 @@ lighting Light ライト
Minimum 最小
Justification 文字組み
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them ファイルの変数とデータセットは読み込まれませんでした (変数: {variables}、データセット: {data_sets})。変数パネルには表示されません
# Select by Color (select.color)
Select by Color カラーで選択
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5112,3 +5112,5 @@ imageTrace Outline კონტური
@msg its zlib compression is damaged მისი zlib შეკუმშვა დაზიანებულია
@msg its Zstandard compression is damaged მისი Zstandard შეკუმშვა დაზიანებულია
@msg it decompresses to more than {_1} MB გაშლისას {_1} MB-ს აღემატება
# Select by Color (select.color)
Select by Color მონიშვნა ფერის მიხედვით
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4782,3 +4782,5 @@ lighting Light 광원
Minimum 최소
Justification 양끝 맞춤
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them 파일의 변수와 데이터 세트를 읽지 않았습니다(변수: {variables}, 데이터 세트: {data_sets}). 변수 패널에 표시되지 않습니다
# Select by Color (select.color)
Select by Color 색상별 선택
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5231,3 +5231,5 @@ swatch Bright Violet Felviolet
Full Justify Volledig uitvullen
Minimum must not exceed Desired, nor Desired Maximum. Minimum mag niet groter zijn dan Gewenst, en Gewenst niet groter dan Maximum.
Justification Uitvullen
# Select by Color (select.color)
Select by Color Selecteren op kleur
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5057,3 +5057,5 @@ mark-style Japanese Japońskie
Minimum must not exceed Desired, nor Desired Maximum. Minimum nie może przekraczać wartości optymalnej, a wartość optymalna maksimum.
Justification Justowanie
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them zmienne i zestawy danych pliku nie zostały wczytane (zmienne: {variables}, zestawy danych: {data_sets}): panel Zmienne ich nie wyświetla
# Select by Color (select.color)
Select by Color Zaznacz według koloru
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5122,3 +5122,5 @@ mark-style Japanese Japonesas
Minimum must not exceed Desired, nor Desired Maximum. O mínimo não pode passar do desejado, nem o desejado do máximo.
Justification Justificação
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them as variáveis e os conjuntos de dados do arquivo não foram lidos (variáveis: {variables}, conjuntos de dados: {data_sets}): o painel Variáveis não os lista
# Select by Color (select.color)
Select by Color Selecionar por Cor
Can't render this file because it contains an unexpected character in line 6 and column 47.
+2
View File
@@ -4815,3 +4815,5 @@ lighting Light Свет
Minimum Минимум
Justification Выключка
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them переменные и наборы данных файла не прочитаны (переменных: {variables}, наборов данных: {data_sets}): панель «Переменные» их не показывает
# Select by Color (select.color)
Select by Color Выделить по цвету
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -5161,3 +5161,5 @@ theme Appearance Utseende
Minimum must not exceed Desired, nor Desired Maximum. Minimum får inte överstiga Önskat, och Önskat inte Maximum.
Justification Justering
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them filens variabler och datauppsättningar lästes inte (variabler: {variables}, datauppsättningar: {data_sets}): panelen Variabler visar dem inte
# Select by Color (select.color)
Select by Color Markera efter färg
Can't render this file because it contains an unexpected character in line 5 and column 25.
+2
View File
@@ -4799,3 +4799,5 @@ lighting Light Світло
Minimum Мінімум
Justification Вирівнювання за шириною
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them змінні та набори даних файлу не прочитано (змінних: {variables}, наборів даних: {data_sets}): панель «Змінні» їх не показує
# Select by Color (select.color)
Select by Color Виділити за кольором
Can't render this file because it contains an unexpected character in line 725 and column 40.
+2
View File
@@ -4799,3 +4799,5 @@ theme Appearance Giao diện
Minimum Tối thiểu
Justification Căn đều
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them các biến và tập dữ liệu của tệp chưa được đọc (biến: {variables}, tập dữ liệu: {data_sets}): bảng Biến không liệt kê chúng
# Select by Color (select.color)
Select by Color Chọn theo màu
Can't render this file because it contains an unexpected character in line 3948 and column 10.
+2
View File
@@ -5041,3 +5041,5 @@ lighting Light 光源
Minimum 最小值
Justification 对齐设置
@msg the file's variables and data sets weren't read (variables: {variables}, data sets: {data_sets}): the Variables panel doesn't list them 文件的变量和数据集未被读取(变量:{variables},数据集:{data_sets}):“变量”面板不会列出它们
# Select by Color (select.color)
Select by Color 按颜色选择
Can't render this file because it contains an unexpected character in line 2 and column 73.
+2
View File
@@ -4094,3 +4094,5 @@ lighting Light 光源
Minimum must not exceed Desired, nor Desired Maximum. 最小值不可超過所需值,所需值不可超過最大值。
Minimum 最小值
Justification 對齊設定
# Select by Color (select.color)
Select by Color 依顏色選取
Can't render this file because it contains an unexpected character in line 6 and column 47.