mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-26 02:37:01 -06:00
Merge pull request #2136 from dotCooCoo/feat/color-panel-options-command
Color panel: Hide Options comes back after a restart, and `ui.colorPanel` sets the mode and options
This commit is contained in:
@@ -1344,6 +1344,7 @@ lighting Light Světlo
|
||||
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
|
||||
Color Panel Options Možnosti panelu Barva
|
||||
Small Caps Kapitálky
|
||||
Small Caps (on the roadmap) Kapitálky (v plánu)
|
||||
Standard Vertical Roman Alignment Standardní svislé zarovnání latinky
|
||||
@@ -3910,6 +3911,7 @@ imageTrace Outline Obrys
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` musí být mezi {min} a {max} (zadáno {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` musí být jedno z {_1}
|
||||
@msg `{key}` must be true or false `{key}` musí být true nebo false
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` musí být grayscale, rgb, hsb, cmyk nebo websafe
|
||||
@msg `{k}` must be [x, y] `{k}` musí být [x, y]
|
||||
@msg `{name}` has no options `{name}` nemá žádné možnosti
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` je vestavěný pracovní prostor; zvolte jiný název
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2694,6 +2694,7 @@
|
||||
Show Modified Geänderte einblenden
|
||||
Show Note Notiz einblenden
|
||||
Show Options Optionen einblenden
|
||||
Color Panel Options Optionen für das Farbbedienfeld
|
||||
Show Package Paket anzeigen
|
||||
Show Panel Bedienfeld einblenden
|
||||
Show Pattern Swatches Musterfelder einblenden
|
||||
@@ -3516,6 +3517,7 @@ theme Appearance Erscheinungsbild
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` muss zwischen {min} und {max} liegen (erhalten: {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` muss einer der folgenden Werte sein: {_1}
|
||||
@msg `{key}` must be true or false `{key}` muss true oder false sein
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` muss grayscale, rgb, hsb, cmyk oder websafe sein
|
||||
@msg `{k}` must be [x, y] `{k}` muss [x, y] sein
|
||||
@msg `{name}` has no options `{name}` hat keine Optionen
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` ist ein integrierter Arbeitsbereich; wählen Sie einen anderen Namen
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2743,6 +2743,7 @@
|
||||
Show Modified Mostrar modificados
|
||||
Show Note Mostrar nota
|
||||
Show Options Mostrar opciones
|
||||
Color Panel Options Opciones del panel Color
|
||||
Show Package Mostrar paquete
|
||||
Show Panel Mostrar panel
|
||||
Show Pattern Swatches Mostrar muestras de motivo
|
||||
@@ -3614,6 +3615,7 @@ axis Both Ambos
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` debe estar entre {min} y {max} (se recibió {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` debe ser uno de estos: {_1}
|
||||
@msg `{key}` must be true or false `{key}` debe ser true o false
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` debe ser grayscale, rgb, hsb, cmyk o websafe
|
||||
@msg `{k}` must be [x, y] `{k}` debe ser [x, y]
|
||||
@msg `{name}` has no options `{name}` no tiene opciones
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` es un espacio de trabajo integrado; elige otro nombre
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2740,6 +2740,7 @@
|
||||
Show Modified Afficher les éléments modifiés
|
||||
Show Note Afficher la note
|
||||
Show Options Afficher les options
|
||||
Color Panel Options Options du panneau Couleur
|
||||
Show Package Afficher le dossier d’assemblage
|
||||
Show Panel Afficher le panneau
|
||||
Show Pattern Swatches Afficher les nuances de motif
|
||||
@@ -3611,6 +3612,7 @@ axis Both Les deux
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` doit être compris entre {min} et {max} (reçu : {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` doit valoir l’une de ces valeurs : {_1}
|
||||
@msg `{key}` must be true or false `{key}` doit valoir true ou false
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` doit valoir grayscale, rgb, hsb, cmyk ou websafe
|
||||
@msg `{k}` must be [x, y] `{k}` doit être [x, y]
|
||||
@msg `{name}` has no options `{name}` n’a pas d’options
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` est un espace de travail intégré ; choisissez un autre nom
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3325,6 +3325,7 @@
|
||||
Show Modified Módosultak megjelenítése
|
||||
Show Note Megjegyzés megjelenítése
|
||||
Show Options Beállítások megjelenítése
|
||||
Color Panel Options Szín panel beállításai
|
||||
Show Package Csomag megjelenítése
|
||||
Show Panel Panel megjelenítése
|
||||
Show Pattern Swatches Mintázat-színminták megjelenítése
|
||||
@@ -4103,6 +4104,7 @@ imageTrace Outline Körvonal
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}`: {min} és {max} közötti érték kell (kapott érték: {x})
|
||||
@msg `{key}` must be one of {_1} `{key}`: ezek egyike kell: {_1}
|
||||
@msg `{key}` must be true or false `{key}`: true vagy false kell
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode`: grayscale, rgb, hsb, cmyk vagy websafe kell
|
||||
@msg `{k}` must be [x, y] `{k}`: [x, y] kell
|
||||
@msg `{name}` has no options ennek nincsenek beállításai: `{name}`
|
||||
@msg `{name}` is a built-in workspace; choose another name beépített munkaterület: `{name}`; válassz másik nevet
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2745,6 +2745,7 @@
|
||||
Show Modified Mostra modificati
|
||||
Show Note Mostra nota
|
||||
Show Options Mostra opzioni
|
||||
Color Panel Options Opzioni pannello Colore
|
||||
Show Package Mostra pacchetto
|
||||
Show Panel Mostra pannello
|
||||
Show Pattern Swatches Mostra campioni motivo
|
||||
@@ -3616,6 +3617,7 @@ axis Both Entrambi
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` deve essere compreso tra {min} e {max} (ricevuto {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` deve essere uno dei seguenti: {_1}
|
||||
@msg `{key}` must be true or false `{key}` deve essere true o false
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` deve essere grayscale, rgb, hsb, cmyk o websafe
|
||||
@msg `{k}` must be [x, y] `{k}` deve essere [x, y]
|
||||
@msg `{name}` has no options `{name}` non ha opzioni
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` è un'area di lavoro integrata; scegli un altro nome
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2564,6 +2564,7 @@
|
||||
Show List View リスト表示
|
||||
Show Note メモを表示
|
||||
Show Options オプションを表示
|
||||
Color Panel Options カラーパネルオプション
|
||||
Show Package パッケージを表示
|
||||
Show Panel パネルを表示
|
||||
Show Perspective Grid 遠近グリッドを表示
|
||||
@@ -4013,6 +4014,7 @@ theme Appearance 外観
|
||||
@msg Opened {url} {url} を開きました
|
||||
@msg No saved views (View → New View…) 保存した表示はありません (表示 → 新規表示…)
|
||||
@msg `command` must be a command whose menu item opens a dialog (see ui.menuDialog) `command` には、メニュー項目がダイアログを開くコマンドを指定してください (ui.menuDialog を参照)
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` には grayscale、rgb、hsb、cmyk、websafe のいずれかを指定してください
|
||||
@msg `{key}` must be true or false `{key}` には true または false を指定してください
|
||||
@msg brightness must be dark|mediumDark|mediumLight|light brightness には dark|mediumDark|mediumLight|light のいずれかを指定してください
|
||||
@msg index must be a number or first, previous, next or last index には数値、または first、previous、next、last のいずれかを指定してください
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2558,6 +2558,7 @@
|
||||
Show List View 목록 보기 표시
|
||||
Show Note 메모 표시
|
||||
Show Options 옵션 표시
|
||||
Color Panel Options 색상 패널 옵션
|
||||
Show Package 패키지 표시
|
||||
Show Panel 패널 표시
|
||||
Show Perspective Grid 원근 격자 표시
|
||||
@@ -3991,6 +3992,7 @@ theme Appearance 외관
|
||||
@msg Opened {url} {url}을(를) 열었습니다
|
||||
@msg No saved views (View → New View…) 저장된 보기가 없습니다(보기 → 새 보기…)
|
||||
@msg `command` must be a command whose menu item opens a dialog (see ui.menuDialog) `command`는 메뉴 항목이 대화상자를 여는 명령이어야 합니다(ui.menuDialog 참조)
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode`은(는) grayscale, rgb, hsb, cmyk, websafe 중 하나여야 합니다
|
||||
@msg `{key}` must be true or false `{key}`은(는) true 또는 false여야 합니다
|
||||
@msg brightness must be dark|mediumDark|mediumLight|light brightness는 dark|mediumDark|mediumLight|light 중 하나여야 합니다
|
||||
@msg index must be a number or first, previous, next or last index는 숫자이거나 first, previous, next, last 중 하나여야 합니다
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1256,6 +1256,7 @@ lighting Light Światło
|
||||
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
|
||||
Color Panel Options Opcje panelu Kolor
|
||||
Small Caps Kapitaliki
|
||||
Small Caps (on the roadmap) Kapitaliki (w planach)
|
||||
Standard Vertical Roman Alignment Standardowe pionowe wyrównanie łacińskie
|
||||
@@ -3724,6 +3725,7 @@ imageTrace Outline Kontur
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` musi mieścić się w zakresie od {min} do {max} (podano {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` musi mieć jedną z wartości: {_1}
|
||||
@msg `{key}` must be true or false `{key}` musi mieć wartość true lub false
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` musi mieć wartość grayscale, rgb, hsb, cmyk lub websafe
|
||||
@msg `{k}` must be [x, y] `{k}` musi mieć postać [x, y]
|
||||
@msg `{name}` has no options `{name}` nie ma opcji
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` to wbudowany obszar roboczy; wybierz inną nazwę
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2741,6 +2741,7 @@
|
||||
Show Modified Показать изменённые
|
||||
Show Note Показать примечание
|
||||
Show Options Показать параметры
|
||||
Color Panel Options Параметры панели «Цвет»
|
||||
Show Package Показать пакет
|
||||
Show Panel Показать панель
|
||||
Show Pattern Swatches Показать образцы узоров
|
||||
@@ -3612,6 +3613,7 @@ axis Both Оба
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` должно быть от {min} до {max} (получено {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` должно быть одним из: {_1}
|
||||
@msg `{key}` must be true or false `{key}` должно быть true или false
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` должно быть grayscale, rgb, hsb, cmyk или websafe
|
||||
@msg `{k}` must be [x, y] `{k}` должно быть [x, y]
|
||||
@msg `{name}` has no options `{name}` не имеет параметров
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` — встроенная рабочая среда; выберите другое имя
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2737,6 +2737,7 @@
|
||||
Show Modified Показати змінені
|
||||
Show Note Показати примітку
|
||||
Show Options Показати параметри
|
||||
Color Panel Options Параметри панелі «Колір»
|
||||
Show Package Показати пакет
|
||||
Show Panel Показати панель
|
||||
Show Pattern Swatches Показати зразки візерунків
|
||||
@@ -3600,6 +3601,7 @@ axis Both Обидві
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` має бути від {min} до {max} (отримано {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` має бути одним з: {_1}
|
||||
@msg `{key}` must be true or false `{key}` має бути true або false
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` має бути grayscale, rgb, hsb, cmyk або websafe
|
||||
@msg `{k}` must be [x, y] `{k}` має бути [x, y]
|
||||
@msg `{name}` has no options `{name}` не має параметрів
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` - вбудоване робоче середовище; виберіть інше ім’я
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 715 and column 40.
|
@@ -3048,6 +3048,7 @@
|
||||
Show Modified Hiện đã sửa đổi
|
||||
Show Note Hiện ghi chú
|
||||
Show Options Hiện tùy chọn
|
||||
Color Panel Options Tùy chọn bảng màu
|
||||
Show Package Hiện gói
|
||||
Show Panel Hiện bảng
|
||||
Show Pattern Swatches Hiện mẫu họa tiết
|
||||
@@ -3733,6 +3734,7 @@ theme Appearance Giao diện
|
||||
@msg `{key}` must be between {min} and {max} (got {x}) `{key}` phải nằm trong khoảng {min} đến {max} (nhận được {x})
|
||||
@msg `{key}` must be one of {_1} `{key}` phải là một trong {_1}
|
||||
@msg `{key}` must be true or false `{key}` phải là true hoặc false
|
||||
@msg `mode` must be grayscale, rgb, hsb, cmyk or websafe `mode` phải là grayscale, rgb, hsb, cmyk hoặc websafe
|
||||
@msg `{k}` must be [x, y] `{k}` phải là [x, y]
|
||||
@msg `{name}` has no options `{name}` không có tùy chọn
|
||||
@msg `{name}` is a built-in workspace; choose another name `{name}` là không gian làm việc tích hợp sẵn; hãy chọn tên khác
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3706 and column 10.
|
@@ -2594,6 +2594,7 @@
|
||||
Show Modified 显示已修改
|
||||
Show Note 显示注解
|
||||
Show Options 显示选项
|
||||
Color Panel Options 颜色面板选项
|
||||
Show Package 显示打包
|
||||
Show Panel 显示面板
|
||||
Show Pattern Swatches 显示图案色板
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2723,6 +2723,7 @@
|
||||
Show Modified 顯示已修改
|
||||
Show Note 顯示註解
|
||||
Show Options 顯示選項
|
||||
Color Panel Options 顏色面板選項
|
||||
Show Package 顯示封裝
|
||||
Show Panel 顯示面板
|
||||
Show Pattern Swatches 顯示圖樣色票
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -620,6 +620,12 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
|
||||
"",
|
||||
"{library: swatch library id or name (see swatch.library.list) | \"document\" (the document's swatches) | \"\" or null (no limit)} limit the Color Guide panel's colours to that library: every harmony colour and variation snaps to its nearest colour, as color.harmony {limitTo} answers (ui.inspect: ui.color_guide_limit) → {limitTo, name}",
|
||||
),
|
||||
(
|
||||
"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 (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}",
|
||||
),
|
||||
(
|
||||
"ui.savePdfDialog",
|
||||
"Save PDF Dialog",
|
||||
@@ -1425,6 +1431,7 @@ pub fn run_ui_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<R
|
||||
"ui.widthPointEdit" => crate::dialogs::width_point::open(app, p),
|
||||
"ui.corners" => crate::dialogs::corners::open(app, p),
|
||||
"ui.colorGuideLimit" => crate::panels::color_guide::set_limit(app, p),
|
||||
"ui.colorPanel" => crate::panels::color::command(app, p),
|
||||
"ui.savePdfDialog" => crate::dialogs::open_save_pdf(app, p),
|
||||
"file.exportAs" if s("path").is_none() => {
|
||||
crate::dialogs::open_export_as(app, s("format").as_deref(), p);
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
//! model and shows the defaults for new art; the app keeps it between sessions). Alt-clicking the
|
||||
//! spectrum or a chip paints the inactive proxy; Shift-clicking the spectrum cycles the modes;
|
||||
//! 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.
|
||||
//! 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.
|
||||
|
||||
use egui::{Color32, Rect, Sense, Stroke, StrokeKind, Ui, vec2};
|
||||
use serde_json::json;
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_color::{Color, GradientKind, Paint};
|
||||
|
||||
use super::{active_paint, color_json, live_run, pstate, set_pstate};
|
||||
@@ -251,8 +252,21 @@ pub(crate) fn gamut_fix(app: &mut VectorcraftApp, ctx: &egui::Context, key: &str
|
||||
/// Serde reader for the saved panel mode ([`crate::UiState::color_mode`]): a menu mode, else none,
|
||||
/// so an unknown value doesn't lose the rest of the preferences.
|
||||
pub fn deserialize_mode<'de, D: serde::Deserializer<'de>>(d: D) -> Result<Option<Mode>, D::Error> {
|
||||
let v = <serde_json::Value as serde::Deserialize>::deserialize(d)?;
|
||||
Ok(Mode::ALL.into_iter().find(|m| serde_json::to_value(m).is_ok_and(|id| id == v)))
|
||||
let v = <Value as serde::Deserialize>::deserialize(d)?;
|
||||
Ok(menu_mode(&v))
|
||||
}
|
||||
|
||||
/// The menu mode whose id (`"grayscale"`, `"rgb"`, `"hsb"`, `"cmyk"`, `"websafe"`) is `v`.
|
||||
fn menu_mode(v: &Value) -> Option<Mode> {
|
||||
Mode::ALL.into_iter().find(|m| serde_json::to_value(m).is_ok_and(|id| id == *v))
|
||||
}
|
||||
|
||||
/// Serde reader for the saved Hide Options ([`crate::UiState::color_hide_options`]): `true` hides
|
||||
/// the options and any other value shows them, so an unknown value doesn't lose the rest of the
|
||||
/// preferences.
|
||||
pub fn deserialize_hide_options<'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_default())
|
||||
}
|
||||
|
||||
/// The mode the panel shows `color` in: with nothing selected (the defaults for new art) the mode
|
||||
@@ -366,7 +380,13 @@ impl Target {
|
||||
|
||||
/// The active proxy's colour or gradient stop; no colour for None, patterns and a "?" proxy.
|
||||
fn target(app: &VectorcraftApp, ui: &Ui) -> Target {
|
||||
if super::active_mixed(app, ui.ctx()) {
|
||||
target_with(app, super::active_mixed(app, ui.ctx()))
|
||||
}
|
||||
|
||||
/// [`target`] with `mixed` for a "?" active proxy: the panel reads it from its per-frame cache,
|
||||
/// `ui.colorPanel` from the session.
|
||||
fn target_with(app: &VectorcraftApp, mixed: bool) -> Target {
|
||||
if mixed {
|
||||
return Target::Paint(None, None);
|
||||
}
|
||||
let p = active_paint(app);
|
||||
@@ -439,6 +459,32 @@ fn set_mode(app: &mut VectorcraftApp, tgt: &Target, mode: Mode) {
|
||||
}
|
||||
}
|
||||
|
||||
/// `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).
|
||||
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 (fill, stroke) = app.session.proxy_mixed();
|
||||
let mixed = if app.session.fill_active { fill } else { stroke };
|
||||
if let Some(m) = mode {
|
||||
set_mode(app, &target_with(app, mixed), m);
|
||||
}
|
||||
if let Some(shown) = options {
|
||||
app.ui.color_hide_options = !shown;
|
||||
}
|
||||
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}))
|
||||
}
|
||||
|
||||
/// Tint mode's rows: the swatch's chip and name, and the T slider and field. Returns a new tint
|
||||
/// (0..1) and its phase.
|
||||
fn tint_rows(ui: &mut Ui, tint: &Tint, slider_w: f32, field_w: f32) -> Option<(f32, Live)> {
|
||||
@@ -494,7 +540,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let mode = shown_mode(app, color.as_ref());
|
||||
let alt = super::alt_held(ui);
|
||||
// Hide Options: just the proxy and the spectrum.
|
||||
if pstate::<bool>(ui.ctx(), "color-hide-options") {
|
||||
if app.ui.color_hide_options {
|
||||
let hit = ui
|
||||
.horizontal(|ui| {
|
||||
super::proxy(app, ui, 40.0);
|
||||
@@ -650,9 +696,9 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
}
|
||||
|
||||
pub fn menu(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let hidden: bool = pstate(ui.ctx(), "color-hide-options");
|
||||
let hidden = app.ui.color_hide_options;
|
||||
if menu_item(ui, if hidden { tl!("Show Options") } else { tl!("Hide Options") }, true, false) {
|
||||
set_pstate(ui.ctx(), "color-hide-options", !hidden);
|
||||
command(app, &json!({ "options": hidden })).ok();
|
||||
}
|
||||
ui.separator();
|
||||
let tgt = target(app, ui);
|
||||
@@ -1047,9 +1093,77 @@ mod tests {
|
||||
let ctx = egui::Context::default();
|
||||
let (spectrum, full) = frame(&mut app, &ctx, vec![], egui::Modifiers::NONE);
|
||||
assert!(spectrum.is_some());
|
||||
set_pstate(&ctx, "color-hide-options", true);
|
||||
assert_eq!(app.run("ui.colorPanel", json!({"options": false})).unwrap()["options"], false);
|
||||
let (_, hidden) = frame(&mut app, &ctx, vec![], egui::Modifiers::NONE);
|
||||
assert!(hidden <= 44.0 && full > 150.0, "{hidden} / {full}");
|
||||
app.run("ui.colorPanel", json!({"options": true})).unwrap();
|
||||
assert_eq!(frame(&mut app, &ctx, vec![], egui::Modifiers::NONE).1, full);
|
||||
}
|
||||
|
||||
/// Hide Options is kept with the UI state, which the app saves with its preferences. A saved
|
||||
/// value that isn't true or false reads as Show Options, and the rest of the state still loads.
|
||||
#[test]
|
||||
fn hide_options_comes_back_after_a_restart() {
|
||||
let mut app = app();
|
||||
app.run("ui.colorPanel", json!({"options": false})).unwrap();
|
||||
let saved: crate::UiState = serde_json::from_value(serde_json::to_value(&app.ui).unwrap()).unwrap();
|
||||
assert!(saved.color_hide_options);
|
||||
assert_eq!(crate::control::inspect(&app, &egui::Context::default())["ui"]["color_hide_options"], true);
|
||||
for v in [json!(7), json!("hide"), json!({}), Value::Null] {
|
||||
let ui: crate::UiState = serde_json::from_value(json!({"color_hide_options": v, "color_mode": "future", "place_link": false})).unwrap();
|
||||
assert_eq!((ui.color_hide_options, ui.color_mode, ui.place_link), (false, None, false), "{v}");
|
||||
}
|
||||
}
|
||||
|
||||
/// `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]
|
||||
fn ui_color_panel_picks_a_mode_as_the_menu_does() {
|
||||
let mut app = app();
|
||||
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!(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");
|
||||
assert_eq!(app.run("ui.colorPanel", json!({"mode": "cmyk"})).unwrap()["shown"], "cmyk");
|
||||
assert!(matches!(crate::panels::current_paints(&app).0.color(), Some(Color::Cmyk { .. })), "CMYK converts the color");
|
||||
app.run("edit.undo", json!({})).unwrap();
|
||||
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"}));
|
||||
// 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();
|
||||
assert_eq!(app.run("ui.colorPanel", json!({})).unwrap()["shown"], "tint");
|
||||
}
|
||||
|
||||
/// A mode the panel menu doesn't list, Lab included, and an options value that isn't true or
|
||||
/// false answer an error, and the command then changes nothing.
|
||||
#[test]
|
||||
fn ui_color_panel_answers_an_error_for_a_mode_off_the_menu() {
|
||||
let mut app = app();
|
||||
for m in [json!("lab"), json!("oklch"), json!("hsl"), json!("future"), json!("RGB"), json!(3)] {
|
||||
let e = app.run("ui.colorPanel", json!({"mode": m})).unwrap_err();
|
||||
assert_eq!(e, "`mode` must be grayscale, rgb, hsb, cmyk or websafe", "{m}");
|
||||
}
|
||||
assert_eq!(app.run("ui.colorPanel", json!({"mode": "cmyk", "options": "no"})).unwrap_err(), "`options` must be true or false");
|
||||
assert_eq!((app.ui.color_mode, app.ui.color_hide_options), (None, false));
|
||||
}
|
||||
|
||||
/// `ui.colorPanel` answers every junk parameter, with and without a document, without a panic.
|
||||
#[test]
|
||||
fn ui_color_panel_answers_junk_params_without_a_panic() {
|
||||
let doc = crate::menus::UI_COMMANDS.iter().find(|c| c.0 == "ui.colorPanel").expect("registered").3;
|
||||
let mut app = app();
|
||||
app.run("paint.setFill", json!({"color": "#336699"})).unwrap();
|
||||
for p in vectorcraft_testkit::strategies::junk_params(doc, "/nonexistent").into_iter().chain(vectorcraft_testkit::strategies::junk_values()) {
|
||||
let _ = app.run("ui.colorPanel", p);
|
||||
}
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
assert_eq!(app.run("ui.colorPanel", json!({"mode": "cmyk"})).unwrap()["mode"], "cmyk");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -380,6 +380,10 @@ pub struct UiState {
|
||||
/// shows the defaults for new art ([`crate::panels::color::deserialize_mode`]).
|
||||
#[serde(default, deserialize_with = "crate::panels::color::deserialize_mode")]
|
||||
pub color_mode: Option<crate::panels::color::Mode>,
|
||||
/// Color panel: Hide Options, which leaves just the proxy and the spectrum (`ui.colorPanel`,
|
||||
/// [`crate::panels::color::deserialize_hide_options`]).
|
||||
#[serde(default, deserialize_with = "crate::panels::color::deserialize_hide_options")]
|
||||
pub color_hide_options: bool,
|
||||
/// The SVG Options chosen last (`svg` object of the export/save commands; null: never used).
|
||||
#[serde(default)]
|
||||
pub svg_options: Value,
|
||||
@@ -715,6 +719,7 @@ impl Default for UiState {
|
||||
color_guide_limit: String::new(),
|
||||
align_to: Default::default(),
|
||||
color_mode: None,
|
||||
color_hide_options: false,
|
||||
svg_options: Value::Null,
|
||||
place_link: true,
|
||||
dialog_file: None,
|
||||
|
||||
@@ -207,6 +207,13 @@ 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 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`,
|
||||
`colorTheme.addToSwatches`, `swatch.newGroup` for the theme being made), and `colorTheme.list` reads the library.
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user