mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-11 16:33:22 -06:00
M3.58: gradient libraries; Swatch Options renames gradient swatches; Alt-drop replaces a swatch
Window > Swatch Libraries > Gradients lists five generated gradient
libraries (Spectrum, Sky, Neutral incl. fades to transparent, Duotone,
Radial Glows); the library panel's menu lists them too.
Swatch Options on a gradient swatch shows its name and the gradient; OK
renames it. Alt-dropping an edited gradient (or a colour) on a swatch of its
kind in the Swatches panel replaces it, via swatch.edit {paint}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
786f2c05d3
commit
3a79e6d922
@@ -46,7 +46,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Swatch Options",
|
||||
["Window", "Swatches"],
|
||||
None,
|
||||
"{name, newName?, color?, mode?: \"gray\"|\"rgb\"|\"hsb\"|\"cmyk\"|\"web\" (convert the colour), global?, spot? (spot colours are always global)} edit a swatch in any colour group, as one undo step. Fills, strokes and text linked to a global swatch take its new colour and name; turning Global off unlinks them (they keep their colour). Colour, mode and spot apply to solid colours only → {name, relinked: paints changed}",
|
||||
"{name, newName?, color?, mode?: \"gray\"|\"rgb\"|\"hsb\"|\"cmyk\"|\"web\" (convert the colour), global?, spot? (spot colours are always global), paint?: paint.setFill params ({color}, {gradient}, {swatch} or {pattern}) replacing the swatch's colour, gradient or pattern with one of the same kind} edit a swatch in any colour group, as one undo step. Fills, strokes and text linked to a global swatch take its new colour and name; turning Global off unlinks them (they keep their colour). Colour, mode and spot apply to solid colours only → {name, relinked: paints changed}",
|
||||
has_doc,
|
||||
swatch_edit
|
||||
),
|
||||
@@ -474,9 +474,21 @@ fn swatch_edit(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
if solid.is_none() && (given("color") || given("mode") || bool_or(p, "spot", false)) {
|
||||
return Err(bad(C, "colour, mode and spot apply to solid-colour swatches only"));
|
||||
}
|
||||
// A replacement paint of the swatch's kind (a dropped colour or edited gradient).
|
||||
let paint = match p.get("paint").filter(|v| !v.is_null()) {
|
||||
Some(v) => match (paint_from(s, v)?, &sw.paint) {
|
||||
(Some(Paint::Solid { color, .. }), Paint::Solid { .. }) => Some(Paint::solid(color)),
|
||||
(Some(Paint::Gradient(g)), Paint::Gradient(_)) => {
|
||||
Some(Paint::Gradient(Box::new(vectorcraft_color::GradientPaint { geom: None, swatch: None, ..*g })))
|
||||
}
|
||||
(Some(new @ Paint::Pattern { .. }), Paint::Pattern { .. }) => Some(new),
|
||||
_ => return Err(bad(C, format!("`{name}` takes a paint of its own kind (colour, gradient or pattern)"))),
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
let mut color = match p.get("color").filter(|v| !v.is_null()) {
|
||||
Some(v) => Some(color_value(v).ok_or_else(|| bad(C, format!("bad color {v}")))?),
|
||||
None => solid,
|
||||
None => paint.as_ref().and_then(Paint::color).or(solid),
|
||||
};
|
||||
if let (Some(c), Some(m)) = (color, str_param(p, "mode")) {
|
||||
color = Some(convert_to_mode(c, m, C)?);
|
||||
@@ -490,8 +502,13 @@ fn swatch_edit(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
w.name = to.clone();
|
||||
w.spot = spot;
|
||||
w.global = global;
|
||||
if let (Some(c), Paint::Solid { color: wc, .. }) = (color, &mut w.paint) {
|
||||
*wc = c;
|
||||
match (color, &mut w.paint) {
|
||||
(Some(c), Paint::Solid { color: wc, .. }) => *wc = c,
|
||||
(_, wp) => {
|
||||
if let Some(new) = paint {
|
||||
*wp = new;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(d.map_solid_paints(&mut |c, l| relink.apply(c, l)))
|
||||
})?;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_color::libraries::{SWATCH_LIBRARIES, builtin_library};
|
||||
use vectorcraft_color::libraries::{BuiltinLibrary, GRADIENT_LIBRARIES, SWATCH_LIBRARIES, builtin_library};
|
||||
use vectorcraft_color::palette_io::{self, PaletteFormat};
|
||||
use vectorcraft_color::{Paint, Swatch, SwatchGroup, SwatchLibrary, default_swatches};
|
||||
|
||||
@@ -23,7 +23,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Swatch Libraries",
|
||||
[],
|
||||
None,
|
||||
"{} → {libraries: [{id, name, category: \"builtIn\"|\"user\" (User Defined: the library files in the user library folder, rescanned now)|\"loaded\" (swatch.library.load), count, path?}], userFolder} every library the library panel opens, in menu order",
|
||||
"{} → {libraries: [{id, name, category: \"builtIn\"|\"gradients\"|\"user\" (User Defined: the library files in the user library folder, rescanned now)|\"loaded\" (swatch.library.load), count, path?}], userFolder} every library the library panel opens, in menu order",
|
||||
always,
|
||||
list
|
||||
),
|
||||
@@ -156,25 +156,34 @@ fn stem(name: &str) -> &str {
|
||||
pub struct LibraryInfo {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
/// "builtIn", "user" or "loaded".
|
||||
/// "builtIn", "gradients", "user" or "loaded".
|
||||
pub category: &'static str,
|
||||
}
|
||||
|
||||
/// Every library, in menu order: built-in, User Defined, loaded.
|
||||
/// The built-in libraries with their categories.
|
||||
fn builtins() -> impl Iterator<Item = (&'static str, &'static BuiltinLibrary)> {
|
||||
SWATCH_LIBRARIES.iter().map(|b| ("builtIn", b)).chain(GRADIENT_LIBRARIES.iter().map(|b| ("gradients", b)))
|
||||
}
|
||||
|
||||
fn builtin_info((category, b): (&'static str, &BuiltinLibrary)) -> LibraryInfo {
|
||||
LibraryInfo { id: b.id.into(), name: b.name.into(), category }
|
||||
}
|
||||
|
||||
/// Every library, in menu order: built-in, gradients, User Defined, loaded.
|
||||
pub fn libraries(s: &Session) -> Vec<LibraryInfo> {
|
||||
let builtin = SWATCH_LIBRARIES.iter().map(|b| LibraryInfo { id: b.id.into(), name: b.name.into(), category: "builtIn" });
|
||||
builtin.chain(s.swatch_libraries.extra.iter().map(|e| e.info.clone())).collect()
|
||||
builtins().map(builtin_info).chain(s.swatch_libraries.extra.iter().map(|e| e.info.clone())).collect()
|
||||
}
|
||||
|
||||
/// Library `key` (an id, or a name in any case) with its info.
|
||||
pub fn library(s: &Session, key: &str) -> Option<(LibraryInfo, Arc<SwatchLibrary>)> {
|
||||
let all = libraries(s);
|
||||
let info = all.iter().find(|l| l.id == key).or_else(|| all.iter().find(|l| l.name.eq_ignore_ascii_case(key)))?.clone();
|
||||
let lib = match s.swatch_libraries.extra.iter().find(|e| e.info.id == info.id) {
|
||||
Some(e) => e.lib.clone(),
|
||||
None => builtin_library(&info.id)?,
|
||||
};
|
||||
Some((info, lib))
|
||||
if let Some(e) = s.swatch_libraries.extra.iter().find(|e| e.info.id == key) {
|
||||
return Some((e.info.clone(), e.lib.clone()));
|
||||
}
|
||||
if let Some(b) = builtins().find(|(_, b)| b.id == key) {
|
||||
return Some((builtin_info(b), builtin_library(key)?));
|
||||
}
|
||||
let id = libraries(s).into_iter().find(|l| l.name.eq_ignore_ascii_case(key))?.id;
|
||||
library(s, &id)
|
||||
}
|
||||
|
||||
fn library_param(s: &Session, p: &Value, cmd: &str) -> Result<(LibraryInfo, Arc<SwatchLibrary>)> {
|
||||
|
||||
Reference in New Issue
Block a user