Files
vectorcraft/crates/engine/src/command_sets.rs
T

116 lines
4.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use super::*;
/// The commands that act on the active artboard (#693), which the app passes as their `artboard`:
/// Paste in Place, in Front and in Back paste onto it, Align to Artboard aligns to it, Distribute
/// Objects and Distribute Spacing with Align to Artboard distribute objects across it, and All on
/// Active Artboard selects on it. A `command.batch` given `artboard` passes it on to each of their
/// steps that names none.
pub const ON_ACTIVE_ARTBOARD: [&str; 7] = [
"edit.pasteInPlace",
"edit.pasteInFront",
"edit.pasteInBack",
"object.align",
"object.distribute",
"object.distributeSpacing",
"select.allOnArtboard",
];
/// The commands that resize the artboards the app passes (Object › Artboards): the app passes the
/// selected artboards to Fit to Artwork Bounds as its `indices`, and the active artboard to Fit to
/// Selected Art as its `index`. A `command.batch` given `artboard` passes it on, as `index`, to
/// each of their steps that names none.
pub const FIT_ACTIVE_ARTBOARD: [&str; 2] = ["artboard.fitToArt", "artboard.fitToSelection"];
/// `(command, param)` pairs the journal records only so a replay reproduces the original run
/// (dates from the clock: `cmd::clock_date`; the artboards the app passes to the
/// [`ON_ACTIVE_ARTBOARD`] and [`FIT_ACTIVE_ARTBOARD`] commands and to a batch); an action leaves
/// them out ([`Session::journal_for_action`]).
const REPLAY_ONLY: [(&str, &str); 14] = [
("file.new", "created"),
("document.save", "modified"),
("file.saveAs", "modified"),
("edit.pasteInPlace", "artboard"),
("edit.pasteInFront", "artboard"),
("edit.pasteInBack", "artboard"),
("object.align", "artboard"),
("object.distribute", "artboard"),
("object.distributeSpacing", "artboard"),
("artboard.fitToArt", "index"),
("artboard.fitToArt", "indices"),
("artboard.fitToSelection", "index"),
("select.allOnArtboard", "artboard"),
("command.batch", "artboard"),
];
/// `p`, the params of command `id`, without its [`REPLAY_ONLY`] values (a batch: its steps').
pub(crate) fn strip_replay_only(id: &str, p: &mut Value) {
let strip = |id: &str, p: &mut Value| {
if let Value::Object(m) = p {
m.retain(|k, _| !REPLAY_ONLY.iter().any(|&(c, key)| c == id && key == k));
}
};
strip(id, p);
// Batches don't nest: one level of steps.
if id == "command.batch"
&& let Some(Value::Array(steps)) = p.get_mut("commands")
{
for step in steps {
let id = step.get("command").and_then(Value::as_str).unwrap_or_default().to_string();
if let Some(p) = step.get_mut("params") {
strip(&id, p);
}
}
}
}
/// Commands that act on the selection and take `ids` by selecting them first (`select.set`, with
/// its checks), then running as on the selection: the result and the selection afterwards are the
/// menu command's (#2130).
pub(crate) const SELECTS_GIVEN_IDS: &[&str] = &[
"edit.duplicate",
"object.arrange.bringForward",
"object.arrange.bringToFront",
"object.arrange.sendBackward",
"object.arrange.sendToBack",
"object.arrange.sendToCurrentLayer",
"object.clippingMask.make",
"object.clippingMask.release",
"object.compoundPath.make",
"object.compoundPath.release",
"object.group",
"object.hide",
"object.lock",
"object.move",
"object.pathfinder.crop",
"object.pathfinder.divide",
"object.pathfinder.exclude",
"object.pathfinder.intersect",
"object.pathfinder.merge",
"object.pathfinder.minusBack",
"object.pathfinder.minusFront",
"object.pathfinder.outline",
"object.pathfinder.trap",
"object.pathfinder.trim",
"object.pathfinder.unite",
"object.reflect",
"object.rotate",
"object.scale",
"object.shear",
"object.ungroup",
];
/// The non-empty `ids` given to a command whose params description names `ids` as a key (the
/// key callers outside the app may pass it, [`cmd::params::takes_key`]), or its `id` as `ids` of
/// one when no `ids` are given and the description takes `id` so
/// ([`cmd::params::id_stands_for_ids`]), as [`cmd::targets`] reads them.
pub(crate) fn given_ids(description: &'static str, params: &Value) -> Option<Vec<NodeId>> {
if !cmd::params::takes_key(description, "ids") {
return None;
}
match params.get("ids").filter(|v| !v.is_null()) {
Some(_) => cmd::ids_param(params, "ids"),
None => cmd::id_param(params, "id").filter(|_| cmd::params::id_stands_for_ids(description)).map(|id| vec![id]),
}
.filter(|ids| !ids.is_empty())
}