Merge pull request #6744 from dotCooCoo/feat/color-show-recent-colors

Color: the panel menu's Show Recent Colors shows or hides the Recent Colors row
This commit is contained in:
BFlat
2026-11-12 09:55:35 +07:00
committed by GitHub
35 changed files with 164 additions and 19 deletions
+1 -1
View File
@@ -1212,7 +1212,7 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
"ui.colorPanel",
"Color Panel Options",
"",
"{mode?: grayscale|rgb|hsb|cmyk|websafe, options?: bool} pick the Color panel's mode as its panel menu does (the active color converts to the mode's model as one undo step), and Show Options (true) or Hide Options (false); both are kept with the preferences; RGB, HSB, Web Safe RGB and hex values use the working RGB space (ui.inspect: ui.color_mode, ui.color_hide_options) → {mode (null: none picked yet), options, shown: the mode the panel shows the color in, or tint for a tint of a global or spot swatch}",
"{mode?: grayscale|rgb|hsb|cmyk|websafe, options?: bool, recentColors?: bool} pick the Color panel's mode as its panel menu does (the active color converts to the mode's model as one undo step), Show Options (true) or Hide Options (false), and check (true) or uncheck (false) Show Recent Colors, which shows or hides the panel's Recent Colors row (applied colors still join the list while it is hidden; the Swatches panel keeps its row); all three are kept with the preferences; RGB, HSB, Web Safe RGB and hex values use the working RGB space (ui.inspect: ui.color_mode, ui.color_hide_options, ui.color_show_recent_colors) → {mode (null: none picked yet), options, recentColors, shown: the mode the panel shows the color in, or tint for a tint of a global or spot swatch}",
),
(
"ui.savePdfDialog",
+1
View File
@@ -3143,6 +3143,7 @@ digits Malayalam Малаялам
Show Modified Показване на променените
Show Note Показване на бележка
Show Options Показване на опциите
Show Recent Colors Показване на скорошните цветове
Show Original Path Показване на оригиналния път
Open this dialog with these settings next time Отваряне на този прозорец с тези настройки следващия път
Auto-Simplify Автоматично опростяване
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1535,6 +1535,7 @@ digits Malayalam Malajalam
Roman Baseline Latinična osnovna linija
Select a text object to edit its character attributes. Odaberite tekstualni objekat da uredite njegove atribute znakova.
Show Options Prikaži opcije
Show Recent Colors Prikaži nedavne boje
Color Panel Options Opcije panela boja
Small Caps Mala velika slova
Small Caps (on the roadmap) Mala velika slova (u planu)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4079,6 +4079,7 @@ digits Malayalam Malaiàlam
Show Modified Mostra els modificats
Show Note Mostra la nota
Show Options Mostra les opcions
Show Recent Colors Mostra els colors recents
Show Original Path Mostra el traçat original
Show Package Mostra el paquet
Show Panel Mostra el panell
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1559,6 +1559,7 @@ digits Malayalam Malajálamské
Roman Baseline Latinková účaří
Select a text object to edit its character attributes. Vyberte textový objekt, abyste mohli upravit atributy jeho znaků.
Show Options Zobrazit možnosti
Show Recent Colors Zobrazit nedávné barvy
Color Panel Options Možnosti panelu Barva
Small Caps Kapitálky
Small Caps (on the roadmap) Kapitálky (v plánu)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1471,6 +1471,7 @@ digits Malayalam Malayalam
Roman Baseline Romersk grundlinje
Select a text object to edit its character attributes. Markér et tekstobjekt for at redigere dets tegnattributter.
Show Options Vis indstillinger
Show Recent Colors Vis seneste farver
Small Caps Kapitæler
Small Caps (on the roadmap) Kapitæler (på vejkortet)
Standard Vertical Roman Alignment Standard lodret romersk justering
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3190,6 +3190,7 @@ digits Malayalam Malayalam
Show Modified Geänderte einblenden
Show Note Notiz einblenden
Show Options Optionen einblenden
Show Recent Colors Zuletzt verwendete Farben einblenden
Show Original Path Originalpfad einblenden
Open this dialog with these settings next time Dieses Dialogfeld nächstes Mal mit diesen Einstellungen öffnen
Auto-Simplify Automatisch vereinfachen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3690,6 +3690,7 @@ digits Malayalam Μαλαγιάλαμ
Show Modified Εμφάνιση τροποποιημένων
Show Note Εμφάνιση σημείωσης
Show Options Εμφάνιση επιλογών
Show Recent Colors Εμφάνιση πρόσφατων χρωμάτων
Show Original Path Εμφάνιση αρχικής διαδρομής
Open this dialog with these settings next time Άνοιγμα αυτού του παραθύρου με αυτές τις ρυθμίσεις την επόμενη φορά
Auto-Simplify Αυτόματη απλοποίηση
Can't render this file because it is too large.
+1
View File
@@ -3229,6 +3229,7 @@ digits Malayalam Malayálam
Show Modified Mostrar modificados
Show Note Mostrar nota
Show Options Mostrar opciones
Show Recent Colors Mostrar colores recientes
Show Original Path Mostrar trazado original
Open this dialog with these settings next time Abrir este cuadro de diálogo con estos ajustes la próxima vez
Auto-Simplify Simplificar automáticamente
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1533,6 +1533,7 @@ digits Malayalam Malajalam
Roman Baseline Latinalainen perusviiva
Select a text object to edit its character attributes. Valitse tekstiobjekti, jonka merkkimääritteitä haluat muokata.
Show Options Näytä asetukset
Show Recent Colors Näytä viimeisimmät värit
Small Caps Kapiteelit
Small Caps (on the roadmap) Kapiteelit (suunnitteilla)
Standard Vertical Roman Alignment Tavallinen pystysuuntainen latinalainen tasaus
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3221,6 +3221,7 @@ digits Malayalam Malayalam
Show Modified Afficher les éléments modifiés
Show Note Afficher la note
Show Options Afficher les options
Show Recent Colors Afficher les couleurs récentes
Show Original Path Afficher le tracé d’origine
Open this dialog with these settings next time Ouvrir cette boîte de dialogue avec ces réglages la prochaine fois
Auto-Simplify Simplifier automatiquement
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4404,6 +4404,7 @@ antiAlias Sharp शार्प
Show Modified संशोधित दिखाएँ
Show Note नोट दिखाएं
Show Options ऑप्शन्स दिखाएँ
Show Recent Colors हाल के रंग दिखाएँ
Show Original Path मूल पाथ दिखाएं
Show Package पैकेज करें दिखाएँ
Show Panel शो पैनल
Can't render this file because it is too large.
+1
View File
@@ -3863,6 +3863,7 @@ mark-style Japanese Japán
Show Modified Módosultak megjelenítése
Show Note Megjegyzés megjelenítése
Show Options Beállítások megjelenítése
Show Recent Colors Legutóbbi színek megjelenítése
Show Original Path Eredeti útvonal megjelenítése
Open this dialog with these settings next time Legközelebb ez a párbeszédablak nyíljon meg ezekkel a beállításokkal
Auto-Simplify Automatikus egyszerűsítés
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1471,6 +1471,7 @@ digits Malayalam Malayalam
Roman Baseline Baseline Romawi
Select a text object to edit its character attributes. Pilih objek teks untuk mengedit atribut karakternya.
Show Options Tampilkan opsi
Show Recent Colors Tampilkan warna terbaru
Small Caps Kapital kecil
Small Caps (on the roadmap) Kapital kecil (masih dalam roadmap)
Standard Vertical Roman Alignment Perataan Romawi vertikal standar
1 # Indonesian (id) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
1471
1472
1473
1474
1475
1476
1477
+1
View File
@@ -3266,6 +3266,7 @@ digits Malayalam Malayalam
Show Modified Mostra modificati
Show Note Mostra nota
Show Options Mostra opzioni
Show Recent Colors Mostra colori recenti
Show Original Path Mostra tracciato originale
Open this dialog with these settings next time Apri questa finestra di dialogo con queste impostazioni la prossima volta
Auto-Simplify Semplifica automaticamente
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3084,6 +3084,7 @@ mark-style Japanese 日本式
Show List View リスト表示
Show Note メモを表示
Show Options オプションを表示
Show Recent Colors 最近使用したカラーを表示
Show Original Path 元のパスを表示
Open this dialog with these settings next time 次回はこの設定でこのダイアログを開く
Auto-Simplify 自動単純化
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1405,6 +1405,7 @@ digits Malayalam მალაიალამური
Roman Baseline ლათინური საბაზისო ხაზი
Select a text object to edit its character attributes. სიმბოლოების ატრიბუტების რედაქტირებისთვის მონიშნეთ ტექსტური ობიექტი.
Show Options პარამეტრების ჩვენება
Show Recent Colors ბოლოდროინდელი ფერების ჩვენება
Small Caps პატარა მთავრული
Small Caps (on the roadmap) პატარა მთავრული (სამომავლო გეგმაშია)
Standard Vertical Roman Alignment სტანდარტული ვერტიკალური ლათინური სწორება
Can't render this file because it is too large.
+1
View File
@@ -3073,6 +3073,7 @@ mark-style Japanese 일본식
Show List View 목록 보기 표시
Show Note 메모 표시
Show Options 옵션 표시
Show Recent Colors 최근 색상 표시
Show Original Path 원래 패스 표시
Open this dialog with these settings next time 다음에 이 설정으로 이 대화상자 열기
Auto-Simplify 자동 단순화
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1485,6 +1485,7 @@ digits Malayalam Malayalam
Roman Baseline Romeinse basislijn
Select a text object to edit its character attributes. Selecteer een tekstobject om de tekenkenmerken ervan te bewerken.
Show Options Opties tonen
Show Recent Colors Recente kleuren tonen
Small Caps Kleine kapitalen
Small Caps (on the roadmap) Kleine kapitalen (op de roadmap)
Standard Vertical Roman Alignment Standaard verticale Romeinse uitlijning
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1471,6 +1471,7 @@ digits Malayalam Malajalam
Roman Baseline Linia bazowa łacińska
Select a text object to edit its character attributes. Zaznacz obiekt tekstowy, aby edytować atrybuty znaków.
Show Options Pokaż opcje
Show Recent Colors Pokaż ostatnie kolory
Color Panel Options Opcje panelu Kolor
Small Caps Kapitaliki
Small Caps (on the roadmap) Kapitaliki (w planach)
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2706,6 +2706,7 @@ digits Malayalam Malaiala
Show List View Mostrar Exibição de Lista
Show Note Mostrar Nota
Show Options Mostrar Opções
Show Recent Colors Mostrar Cores Recentes
Show Original Path Mostrar Caminho Original
Open this dialog with these settings next time Abrir este diálogo com estas configurações na próxima vez
Auto-Simplify Simplificar Automaticamente
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -3261,6 +3261,7 @@ digits Malayalam Малаялам
Show Modified Показать изменённые
Show Note Показать примечание
Show Options Показать параметры
Show Recent Colors Показать последние цвета
Show Original Path Показать исходный контур
Open this dialog with these settings next time Открывать это диалоговое окно с этими параметрами в следующий раз
Auto-Simplify Автоматическое упрощение
Can't render this file because it is too large.
+1
View File
@@ -3153,6 +3153,7 @@ digits Malayalam Malayalam
Show Modified Visa ändrade
Show Note Visa anteckning
Show Options Visa alternativ
Show Recent Colors Visa senaste färger
Show Original Path Visa ursprunglig bana
Open this dialog with these settings next time Öppna den här dialogrutan med de här inställningarna nästa gång
Auto-Simplify Förenkla automatiskt
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -3057,6 +3057,7 @@ digits Malayalam Malayalam
Show Modified Değiştirilenleri Göster
Show Note Notu Göster
Show Options Seçenekleri Göster
Show Recent Colors Son Renkleri Göster
Show Original Path Orijinal Yolu Göster
Color Panel Options Renk Paneli Seçenekleri
Show Package Paketi Göster
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -3258,6 +3258,7 @@ digits Malayalam Малаялам
Show Modified Показати змінені
Show Note Показати примітку
Show Options Показати параметри
Show Recent Colors Показати останні кольори
Show Original Path Показати початковий контур
Open this dialog with these settings next time Наступного разу відкривати це діалогове вікно з цими параметрами
Auto-Simplify Автоматичне спрощення
Can't render this file because it contains an unexpected character in line 182 and column 5.
+1
View File
@@ -3605,6 +3605,7 @@ mark-style Japanese Kiểu Nhật
Show Modified Hiện đã sửa đổi
Show Note Hiện ghi chú
Show Options Hiện tùy chọn
Show Recent Colors Hiện màu gần đây
Show Original Path Hiện đường dẫn gốc
Open this dialog with these settings next time Lần sau mở hộp thoại này với các cài đặt này
Auto-Simplify Tự động đơn giản hóa
Can't render this file because it contains an unexpected character in line 204 and column 5.
+1
View File
@@ -3094,6 +3094,7 @@ digits Malayalam 马拉雅拉姆数字
Show Modified 显示已修改
Show Note 显示注解
Show Options 显示选项
Show Recent Colors 显示最近使用的颜色
Show Original Path 显示原始路径
Open this dialog with these settings next time 下次以这些设置打开此对话框
Auto-Simplify 自动简化
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -4216,6 +4216,7 @@ digits Malayalam 馬來亞拉姆數字
Show Modified 顯示已修改
Show Note 顯示註解
Show Options 顯示選項
Show Recent Colors 顯示最近使用的顏色
Show Original Path 顯示原始路徑
Open this dialog with these settings next time 下次以這些設定開啟此對話方塊
Auto-Simplify 自動簡化
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1 -1
View File
@@ -1213,7 +1213,7 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
"ui.colorPanel",
"Color Panel Options",
"",
"{mode?: grayscale|rgb|hsb|cmyk|websafe, options?: bool} pick the Color panel's mode as its panel menu does (the active color converts to the mode's model as one undo step), and Show Options (true) or Hide Options (false); both are kept with the preferences; RGB, HSB, Web Safe RGB and hex values use the working RGB space (ui.inspect: ui.color_mode, ui.color_hide_options) → {mode (null: none picked yet), options, shown: the mode the panel shows the color in, or tint for a tint of a global or spot swatch}",
"{mode?: grayscale|rgb|hsb|cmyk|websafe, options?: bool, recentColors?: bool} pick the Color panel's mode as its panel menu does (the active color converts to the mode's model as one undo step), Show Options (true) or Hide Options (false), and check (true) or uncheck (false) Show Recent Colors, which shows or hides the panel's Recent Colors row (applied colors still join the list while it is hidden; the Swatches panel keeps its row); all three are kept with the preferences; RGB, HSB, Web Safe RGB and hex values use the working RGB space (ui.inspect: ui.color_mode, ui.color_hide_options, ui.color_show_recent_colors) → {mode (null: none picked yet), options, recentColors, shown: the mode the panel shows the color in, or tint for a tint of a global or spot swatch}",
),
(
"ui.savePdfDialog",
+37 -8
View File
@@ -12,7 +12,10 @@
//! the inactive proxy when Alt is also held;
//! Shift-dragging a slider moves the others in tandem; RGB and HSB show the out-of-gamut warning;
//! Hide Options leaves just the proxy and the spectrum (the app keeps it between sessions too).
//! `ui.colorPanel` picks a mode and shows or hides the options as the panel menu does.
//! Unchecking Show Recent Colors hides the Recent Colors row while applied colors still join the
//! list (the app keeps it between sessions too).
//! `ui.colorPanel` picks a mode, shows or hides the options and checks or unchecks Show Recent
//! Colors as the panel menu does.
use egui::{Color32, Rect, Sense, Stroke, StrokeKind, Ui, vec2};
use serde_json::{Value, json};
@@ -287,6 +290,14 @@ pub fn deserialize_hide_options<'de, D: serde::Deserializer<'de>>(d: D) -> Resul
Ok(v.as_bool().unwrap_or_default())
}
/// Serde reader for the saved Show Recent Colors ([`crate::UiState::color_show_recent_colors`]):
/// `false` hides the row and any other value shows it, so an unknown value doesn't lose the rest
/// of the preferences.
pub fn deserialize_show_recent_colors<'de, D: serde::Deserializer<'de>>(d: D) -> Result<bool, D::Error> {
let v = <Value as serde::Deserialize>::deserialize(d)?;
Ok(v.as_bool().unwrap_or(true))
}
/// The mode the panel shows `color` in: with nothing selected (the defaults for new art) the mode
/// picked last, which the app keeps between sessions, else [`display_mode`].
fn shown_mode(app: &VectorcraftApp, color: Option<&Color>) -> Mode {
@@ -511,16 +522,18 @@ fn recolor(app: &mut VectorcraftApp, ui: &Ui, tgt: &Target, invert: bool, behind
}
}
/// `ui.colorPanel {mode?, options?}`: pick a mode as the panel menu does ([`set_mode`]), and Show
/// Options (true) or Hide Options (false). → {mode, options, shown}: the mode picked last (null:
/// none yet), whether the options show, and the mode the panel shows the color in (`tint` for a
/// tint of a global or spot swatch).
/// `ui.colorPanel {mode?, options?, recentColors?}`: pick a mode as the panel menu does
/// ([`set_mode`]), Show Options (true) or Hide Options (false), and check (true) or uncheck
/// (false) Show Recent Colors. → {mode, options, recentColors, shown}: the mode picked last (null:
/// none yet), whether the options show, whether Show Recent Colors is checked, and the mode the
/// panel shows the color in (`tint` for a tint of a global or spot swatch).
pub(crate) fn command(app: &mut VectorcraftApp, p: &Value) -> Result<Value, String> {
let mode = match p.get("mode") {
None | Some(Value::Null) => None,
Some(v) => Some(menu_mode(v).ok_or("`mode` must be grayscale, rgb, hsb, cmyk or websafe")?),
};
let options = crate::menus::opt_bool(p, "options")?;
let recent = crate::menus::opt_bool(p, "recentColors")?;
let (fill, stroke) = app.session.proxy_mixed();
let mixed = if app.session.fill_active { fill } else { stroke };
if let Some(m) = mode {
@@ -529,12 +542,20 @@ pub(crate) fn command(app: &mut VectorcraftApp, p: &Value) -> Result<Value, Stri
if let Some(shown) = options {
app.ui.color_hide_options = !shown;
}
if let Some(on) = recent {
app.ui.color_show_recent_colors = on;
}
let tgt = target_with(app, mixed);
let shown = match tgt.tint() {
Some(_) => json!("tint"),
None => json!(shown_mode(app, tgt.color().as_ref())),
};
Ok(json!({"mode": app.ui.color_mode, "options": !app.ui.color_hide_options, "shown": shown}))
Ok(json!({
"mode": app.ui.color_mode,
"options": !app.ui.color_hide_options,
"recentColors": app.ui.color_show_recent_colors,
"shown": shown,
}))
}
/// Tint mode's rows: the swatch's chip and name, and the T slider and field. Returns a new tint
@@ -626,8 +647,12 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
(Some(c), _) => components(mode, &c),
(None, _) => vec![0.0; mode.labels().len()],
};
let recent = super::recent_colors_row(app, ui);
widgets::divider(ui);
// Show Recent Colors draws the Recent Colors row; the Swatches panel's row does not read it.
let mut recent = None;
if app.ui.color_show_recent_colors {
recent = super::recent_colors_row(app, ui);
widgets::divider(ui);
}
// An edit of the active colour with its displayed components (`new`), or a colour clicked with
// Alt held for the inactive proxy (`behind`).
let mut new: Option<(Color, Live, Vec<f32>)> = None;
@@ -770,6 +795,10 @@ pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
if menu_item(ui, if hidden { tl!("Show Options") } else { tl!("Hide Options") }, true, false) {
command(app, &json!({ "options": hidden })).ok();
}
let recent = app.ui.color_show_recent_colors;
if menu_item(ui, tl!("Show Recent Colors"), true, recent) {
command(app, &json!({ "recentColors": !recent })).ok();
}
ui.separator();
let tgt = target(app, ui);
let color = tgt.color();
+79 -2
View File
@@ -599,6 +599,83 @@ fn hide_options_comes_back_after_a_restart() {
}
}
/// The panel menu's Show Recent Colors hides the Recent Colors row and shows it again. Applied
/// colors still join the list while the row is hidden, Hide Options hides the row either way, and
/// the Swatches panel keeps its own row.
#[test]
fn show_recent_colors_hides_and_shows_the_row() {
let mut app = app();
app.run("paint.setFill", json!({"color": "#ff0000"})).unwrap();
let ctx = egui::Context::default();
crate::theme::install_fonts(&ctx);
let none = egui::Modifiers::NONE;
// The first recent chip's rect and the panel's height. The second frame's answer counts, since
// egui also answers for a widget the frame before drew.
let chip = |app: &mut VectorcraftApp| {
frame_with(app, &ctx, vec![], none, ("recent", 0usize));
frame_with(app, &ctx, vec![], none, ("recent", 0usize))
};
let (shown, full) = chip(&mut app);
assert!(shown.is_some(), "the row shows by default");
// The item is checked while the row shows.
click_menu_item(&mut app, &ctx, "✓ Show Recent Colors");
assert!(!app.ui.color_show_recent_colors);
let (hidden, short) = chip(&mut app);
assert!(hidden.is_none() && short < full, "the row is hidden: {short} / {full}");
// A color applied while the row is hidden still joins the list.
app.run("paint.setFill", json!({"color": "#00ff00"})).unwrap();
assert_eq!(app.session.recent_colors.first().map(|c| c.to_hex()).as_deref(), Some("#00ff00"));
// The Swatches panel keeps its row (drawn in a context of its own, whose chip ids the Color
// panel's would share).
let mut swatch_chip = None;
let screen_rect = Some(Rect::from_min_size(egui::Pos2::ZERO, vec2(280.0, 700.0)));
let swatches = egui::Context::default();
let mut out = swatches.run_ui(egui::RawInput { screen_rect, ..Default::default() }, |ui| {
crate::panels::swatches::show(&mut app, ui);
swatch_chip = swatches.read_response(ui.scope_id().with(("recent", 0usize))).map(|r| r.rect);
});
out.textures_delta.clear();
assert!(swatch_chip.is_some(), "the Swatches panel still draws its recent colors");
// Show Options leaves the row hidden, and Hide Options hides it with the row checked too.
app.run("ui.colorPanel", json!({"options": false})).unwrap();
app.run("ui.colorPanel", json!({"options": true})).unwrap();
assert!(chip(&mut app).0.is_none(), "Show Options keeps Show Recent Colors unchecked");
click_menu_item(&mut app, &ctx, "Show Recent Colors");
assert!(chip(&mut app).0.is_some(), "checking the item shows the row again");
assert_eq!(app.run("ui.colorPanel", json!({"options": false})).unwrap()["recentColors"], true);
assert!(chip(&mut app).0.is_none(), "Hide Options hides the row");
assert!(app.ui.color_show_recent_colors, "Hide Options leaves Show Recent Colors checked");
let r = app.run("ui.colorPanel", json!({"options": true, "recentColors": false})).unwrap();
assert_eq!((&r["options"], &r["recentColors"]), (&json!(true), &json!(false)));
assert!(chip(&mut app).0.is_none());
app.run("ui.colorPanel", json!({"recentColors": true})).unwrap();
assert_eq!(chip(&mut app).1, full, "the panel is as tall as before");
}
/// Show Recent Colors is kept with the UI state, which the app saves with its preferences. A saved
/// state without it, or with a value that isn't true or false, reads as checked, and the rest of the
/// state still loads. A value that isn't true or false in the command answers an error and changes
/// nothing.
#[test]
fn show_recent_colors_comes_back_after_a_restart() {
let mut app = app();
app.run("ui.colorPanel", json!({"recentColors": false})).unwrap();
let saved: crate::UiState = serde_json::from_value(serde_json::to_value(&app.ui).unwrap()).unwrap();
assert!(!saved.color_show_recent_colors);
assert_eq!(crate::control::inspect(&app, &egui::Context::default())["ui"]["color_show_recent_colors"], false);
let old: crate::UiState = serde_json::from_value(json!({"place_link": false})).unwrap();
assert!(old.color_show_recent_colors, "a state saved before the setting existed shows the row");
for v in [json!(7), json!("hide"), json!({}), Value::Null] {
let ui: crate::UiState = serde_json::from_value(json!({"color_show_recent_colors": v, "place_link": false})).unwrap();
assert_eq!((ui.color_show_recent_colors, ui.place_link), (true, false), "{v}");
}
for v in [json!("no"), json!(0), json!([])] {
let e = app.run("ui.colorPanel", json!({"mode": "cmyk", "options": false, "recentColors": v})).unwrap_err();
assert_eq!(e, "`recentColors` must be true or false", "{v}");
}
assert_eq!((app.ui.color_mode, app.ui.color_hide_options, app.ui.color_show_recent_colors), (None, false, false));
}
/// `ui.colorPanel {mode}` picks a mode as the panel menu does: HSB shows an RGB fill as H, S and
/// B, and CMYK converts it as one undo step.
#[test]
@@ -607,7 +684,7 @@ fn ui_color_panel_picks_a_mode_as_the_menu_does() {
let ctx = egui::Context::default();
app.run("paint.setFill", json!({"color": "#336699"})).unwrap();
let r = app.run("ui.colorPanel", json!({"mode": "hsb"})).unwrap();
assert_eq!(r, json!({"mode": "hsb", "options": true, "shown": "hsb"}));
assert_eq!(r, json!({"mode": "hsb", "options": true, "recentColors": true, "shown": "hsb"}));
assert_eq!(slider_labels(&mut app, &ctx), ["H", "S", "B"]);
assert_eq!(crate::control::inspect(&app, &ctx)["ui"]["color_mode"], "hsb");
assert_eq!(paints_hex(&app).0, "#336699", "HSB keeps the RGB color");
@@ -617,7 +694,7 @@ fn ui_color_panel_picks_a_mode_as_the_menu_does() {
assert!(matches!(crate::panels::current_paints(&app).0.color(), Some(Color::Rgb { .. })), "undo restores it");
assert_eq!(paints_hex(&app).0, "#336699");
// `{}` reads the settings: CMYK stays picked, and the RGB fill shows in its own model.
assert_eq!(app.run("ui.colorPanel", json!({})).unwrap(), json!({"mode": "cmyk", "options": true, "shown": "rgb"}));
assert_eq!(app.run("ui.colorPanel", json!({})).unwrap(), json!({"mode": "cmyk", "options": true, "recentColors": true, "shown": "rgb"}));
// A tint of a global swatch shows Tint mode.
app.run("swatch.new", json!({"name": "Ink", "color": {"c": 0, "m": 1, "y": 0, "k": 0}, "spot": true})).unwrap();
app.run("paint.setFill", json!({"swatch": "Ink", "tint": 50})).unwrap();
+6
View File
@@ -660,6 +660,11 @@ pub struct UiState {
/// [`crate::panels::color::deserialize_hide_options`]).
#[serde(default, deserialize_with = "crate::panels::color::deserialize_hide_options")]
pub color_hide_options: bool,
/// Color panel: Show Recent Colors, which draws its Recent Colors row while the options show
/// (`ui.colorPanel`, [`crate::panels::color::deserialize_show_recent_colors`]). The list of
/// recent colors keeps filling while the row is hidden.
#[serde(default = "yes", deserialize_with = "crate::panels::color::deserialize_show_recent_colors")]
pub color_show_recent_colors: bool,
/// The SVG Options chosen last (`svg` object of the export/save commands; null: never used).
#[serde(default)]
pub svg_options: Value,
@@ -1104,6 +1109,7 @@ impl Default for UiState {
align_spacing: 0.0,
color_mode: None,
color_hide_options: false,
color_show_recent_colors: true,
svg_options: Value::Null,
place_link: true,
dialog_file: None,
+9 -6
View File
@@ -236,12 +236,15 @@ Edit or Apply Colors runs `ui.recolorDialog {colors, library?}` with the harmony
recolours as usual; with nothing selected the colours themselves are the rows and `ui.dialog.confirm` saves them as a
new colour group (`swatch.newGroup`, named by the `groupName` field).
Color panel options: `ui.colorPanel {mode?, options?}` picks the panel's mode as its panel menu does (`grayscale`,
`rgb`, `hsb`, `cmyk` or `websafe`; the active color converts to the mode's model as one undo step) and shows
(`options: true`) or hides (`false`) the options. It answers `{mode, options, shown}`: `mode` is null until a mode is
picked, and `shown` is the mode the panel shows the color in, or `tint` for a tint of a global or spot swatch.
Another mode, `lab` included, answers an error. The desktop app keeps both settings with its preferences, and
`ui.inspect` reports them as `ui.color_mode` and `ui.color_hide_options`.
Color panel options: `ui.colorPanel {mode?, options?, recentColors?}` picks the panel's mode as its panel menu does
(`grayscale`, `rgb`, `hsb`, `cmyk` or `websafe`; the active color converts to the mode's model as one undo step),
shows (`options: true`) or hides (`false`) the options, and checks (`recentColors: true`) or unchecks (`false`) Show
Recent Colors, which shows or hides the panel's Recent Colors row. Applied colors still join the list while the row
is hidden, and the Swatches panel keeps its own row. It answers `{mode, options, recentColors, shown}`: `mode` is null
until a mode is picked, and `shown` is the mode the panel shows the color in, or `tint` for a tint of a global or spot
swatch. Another mode, `lab` included, answers an error, as does an `options` or `recentColors` value that is not true
or false. The desktop app keeps the three settings with its preferences, and `ui.inspect` reports them as
`ui.color_mode`, `ui.color_hide_options` and `ui.color_show_recent_colors`.
Color Themes panel (`window.panel {panel: "colorThemes"}`): its Create tab makes a theme on a harmony wheel and its
My Themes tab lists the saved themes; every action runs a command (`colorTheme.save`, `colorTheme.delete`,
+3 -1
View File
@@ -480,7 +480,9 @@ objects' fills or strokes differ (`fillMixed` / `strokeMixed`, drawn as a "?" pr
In the app's Color panel and Color Picker, RGB, HSB, hex and Web Safe RGB values describe the active working RGB
space. RGB edits preserve the other native channels; HSB uses those same working RGB components. Colors outside
display sRGB retain their native numeric values. `ui.colorPanel` selects the panel mode and `ui.colorPicker`
opens the picker through `run_command` with the remote backend.
opens the picker through `run_command` with the remote backend. `ui.colorPanel {"recentColors": false}` unchecks
the panel menu's Show Recent Colors, which hides the Color panel's Recent Colors row, and `true` shows it again;
applied colors still join the list while it is hidden.
| Tool | Arguments | Notes |
|---|---|---|
+1
View File
@@ -1285,6 +1285,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- **Colour:** a Color Picker (colour field, H/S/B/R/G/B channel slider, HSB/RGB/Lab/CMYK fields, hex, web-only snapping, out-of-gamut correction); the Color panel shows a selected colour in its own model and, with nothing selected, the new-art defaults in the mode picked last, which it keeps between sessions; Alt-click paints the other proxy; proxies look through groups and show "?" for mixed paint; Invert, Complement, Apply Last Color (`,`) and Apply Last Gradient (`.`) keep the colour model; every paint command feeds the recent colours. The Color Guide has 21 harmony rules, Steps and Variation options and Limit to Library. Adjust Color Balance (its Global mode shifts tints) and Saturate preview live; Edit Colors and Recolor also reach meshes, images and patterns. Recolor Artwork has colour reduction, five recolour methods, presets, Limit to Library, a colour-wheel Edit tab and Edit Color Group; a local Color Themes panel saves five-colour themes. Fill/Stroke chips open swatch and mixer popovers (the Properties panel has the Control bar's Fill and Stroke chips, Stroke link and weight spinner, with nothing selected too), panels have Illustrator's Window menu keys (Align Shift+F7, Transform Shift+F8, Pathfinder Cmd+Shift+F9, Layers F7, Character Cmd+T…; every panel can be given one in Edit › Keyboard Shortcuts), and Eyedropper Options pick up and apply chosen attributes (Alt and Shift+Alt, image pixels). An ICC CMYK profile converts straight into the RGB working space (not through sRGB, so a wider space such as Wide Gamut RGB keeps colours sRGB can't hold) with the colour settings' black-point compensation, on the canvas and in RGB exports alike (the built-in Generic CMYK compensates both ways, so RGB black separated to a rich black displays as black again). Fills and strokes can overprint (Attributes panel, Overprint Black options), and CMYK documents blend in inks on screen, in PDF and when flattening. Document Color Mode converts the art, symbols, pattern tiles and swatches through the colour settings: Gray stays Gray, RGB grays separate into light grays in cyan, magenta and yellow only, darker four-color grays and a rich black, or go on the black plate only with `grays: "black"` (also for `document.open {colorMode}`).
Plain Comma and Period, and also Shift+Comma and Shift+Period, apply the last solid color and the last gradient to the active Fill or Stroke proxy in VectorCraft ([Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html), "Select color fill mode" and "Select gradient fill mode").
Recent Colors keeps the last 30 solid colors applied, newest first and each once, and the list stays the same when another document is opened or made active; a 31st color drops the oldest ([Select colors using the Color panel](https://helpx.adobe.com/illustrator/desktop/manage-colors/select-and-adjust-colors/select-colors-using-the-color-panel.html)). The list lasts for the session. In the Color and Swatches panels the chips wrap onto further rows when the panel is too narrow for one row (`paint.recent`). Tests: `recent_colors_keep_thirty_colors_across_documents` in `crates/engine/src/tests/paintproxy.rs`, `all_thirty_recent_colors_wrap_into_a_narrow_panel` in `crates/ui-egui/src/panels/color/tests.rs`.
Unchecking Show Recent Colors in the Color panel's menu hides its Recent Colors row, and checking it shows the row again ([Select colors using the Color panel](https://helpx.adobe.com/illustrator/desktop/manage-colors/select-and-adjust-colors/select-colors-using-the-color-panel.html)). In VectorCraft the item is checked by default and kept between sessions, applied colors still join the list while the row is hidden, Hide Options hides the row either way, and the Swatches panel keeps its row (`ui.colorPanel {recentColors}`). Tests: `show_recent_colors_hides_and_shows_the_row` in `crates/ui-egui/src/panels/color/tests.rs`.
A Cmd/Ctrl-click on the Color panel's spectrum applies Complement and a Cmd/Ctrl+Shift-click applies Invert to the active Fill or Stroke (`paint.complement`, `paint.invert`); with Alt also held, the click recolors the inactive one, as the reference app's [Default keyboard shortcuts](https://web.archive.org/web/20260726060015/https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html) list them.
View › Proof Setup › Color blindness – Tritanopia-type turns Proof Colors on and proofs the canvas with the tritanopia simulation of Brettel, Viénot and Mollon (1997). The Separations Preview panel's Proof Setup list offers the same target (`view.proofSetup {target: "tritanopia"}`). Grays keep their value.
The Separations Preview panel's Gamut Check button reports one color outside the CMYK gamut in the singular and more in the plural, in English and in each language's plural forms (`gamut_check_status_takes_the_plural_form` in `crates/ui-egui/src/i18n/tests.rs`).