mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 10:17:02 -06:00
A Pencil or Paintbrush stroke always left the path it drew or continued selected. The reference app's Pencil and Paintbrush options have Keep selected for this, and VectorCraft's Tool Options had no such row. The Pencil and Paintbrush Tool Options now have a Keep selected checkbox, on by default, which keeps today's behavior. When it is off, a new path is not selected and the selection stays as it was, and a continued path is removed from the selection while the rest stays. The stroke is still one undo step. The option persists like the tools' other options, and path.freehand and brush.freehand take keepSelected. Docs: docs/target-app-parity.md, docs/ui-parity.md, docs/control-protocol.md.
98 lines
4.0 KiB
Rust
98 lines
4.0 KiB
Rust
//! Tool options that persist: a tool keeps them when another tool is chosen and they are saved
|
|
//! with the preferences, as the reference app keeps each tool's options. Options that are the
|
|
//! state of an interaction (pins, a reference point, the text being edited, the files a place
|
|
//! cursor holds) aren't listed: they start afresh.
|
|
//!
|
|
//! Each row names the tools it covers, the store their values live in and the option keys. A row
|
|
//! with a shared store gives every tool it lists one set of values: the Liquify tools share their
|
|
//! Global Brush Dimensions, the Symbolism tools their brush. Otherwise each tool has its own store,
|
|
//! named after its id.
|
|
|
|
/// (tools, the store they share (None: each tool's own), option keys).
|
|
type Row = (&'static [&'static str], Option<&'static str>, &'static [&'static str]);
|
|
|
|
/// The Liquify tools.
|
|
pub const LIQUIFY: &[&str] = &["warp", "twirl", "pucker", "bloat", "scallop", "crystallize", "wrinkle"];
|
|
|
|
/// The Symbolism tools.
|
|
pub const SYMBOLISM: &[&str] =
|
|
&["symbolSprayer", "symbolShifter", "symbolScruncher", "symbolSizer", "symbolSpinner", "symbolStainer", "symbolScreener", "symbolStyler"];
|
|
|
|
const ROWS: &[Row] = &[
|
|
(&["dimension"], None, &["mode", "style"]),
|
|
// Global Brush Dimensions.
|
|
(LIQUIFY, Some("liquify"), &["width", "height", "angle", "intensity", "usePressure", "showBrush"]),
|
|
(LIQUIFY, None, &["detail", "simplify", "simplifyOn", "rate", "complexity", "horizontal", "vertical", "affectAnchors", "affectIn", "affectOut"]),
|
|
(SYMBOLISM, Some("symbolism"), &["diameter", "intensity", "density"]),
|
|
(&["mirrorCut"], None, &["axis", "keep"]),
|
|
(&["puppetWarp"], None, &["showMesh", "expand"]),
|
|
(&["arc"], None, &["closed"]),
|
|
(&["spiral"], None, &["decay", "segments", "clockwise"]),
|
|
(&["rectangularGrid"], None, &["rows", "columns", "rowSkew", "columnSkew", "frame", "fill"]),
|
|
(&["polarGrid"], None, &["concentric", "radial", "concentricSkew", "radialSkew", "compound", "fill"]),
|
|
(&["pencil", "paintbrush"], None, &["fidelity", "fill", "keepSelected", "editWithin", "closeWithin"]),
|
|
(&["smooth"], None, &["fidelity"]),
|
|
(&["blobBrush", "eraser"], None, &["size"]),
|
|
(&["polygon"], None, &["sides"]),
|
|
(&["star"], None, &["points"]),
|
|
(&["freeTransform"], None, &["constrain"]),
|
|
(&["artboard"], None, &["moveArt", "scaleArt"]),
|
|
// Flare Tool Options (`extra::FLARE_OPTIONS` and the Rays and Rings checkboxes).
|
|
(
|
|
&["flare"],
|
|
None,
|
|
&[
|
|
"diameter",
|
|
"opacity",
|
|
"brightness",
|
|
"growth",
|
|
"fuzziness",
|
|
"raysOn",
|
|
"rays",
|
|
"longest",
|
|
"rayFuzziness",
|
|
"ringsOn",
|
|
"pathLength",
|
|
"rings",
|
|
"largest",
|
|
"direction",
|
|
],
|
|
),
|
|
];
|
|
|
|
/// The stores `tool`'s persistent options live in, each with the option keys it holds.
|
|
pub fn stores(tool: &str) -> impl Iterator<Item = (&'static str, &'static [&'static str])> + '_ {
|
|
ROWS.iter().filter_map(move |(tools, shared, keys)| {
|
|
let id = tools.iter().find(|t| **t == tool)?;
|
|
Some((shared.unwrap_or(id), *keys))
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn every_listed_option_is_one_the_tool_reports() {
|
|
for (tools, _, keys) in ROWS {
|
|
for id in *tools {
|
|
assert!(crate::tool_info(id).is_some(), "{id} is a tool");
|
|
let opts = crate::create(id).options();
|
|
for k in *keys {
|
|
assert!(opts.get(*k).is_some(), "{id} reports `{k}` in {opts}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn liquify_tools_share_the_global_brush() {
|
|
let warp: Vec<_> = stores("warp").collect();
|
|
let twirl: Vec<_> = stores("twirl").collect();
|
|
assert_eq!(warp[0], twirl[0]);
|
|
assert_eq!(warp[0].0, "liquify");
|
|
assert_eq!((warp[1].0, twirl[1].0), ("warp", "twirl"));
|
|
assert_eq!(stores("selection").count(), 0);
|
|
}
|
|
}
|