mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 05:07:51 -06:00
Shaper: dragging a shape out of a Shaper Group's bounds takes it out of the group
Squashed from #4415 onto main.
This commit is contained in:
@@ -15,7 +15,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Transform",
|
||||
[],
|
||||
None,
|
||||
"{matrix: [a,b,c,d,e,f], copy?: bool, ids?, strokes?: bool, corners?: bool, typeAreas?: bool, anchors?: bool, objects?: bool (Transform Objects, default true; false: the art stays and, with patterns, only its pattern tiles transform), patterns?: bool (Transform Patterns: pattern fills and strokes transform with the art; default: prefs transformPatternTiles)} apply an affine to the selection (or ids); anchors (without ids or copy): paths with anchors selected with Direct Selection have only those anchors and their handles transformed, as the Transform tools and object.move/rotate/scale/reflect/shear do (default: the whole objects); strokes/corners: Scale Strokes & Effects / Scale Corners (default: the preferences); typeAreas: area type among them (not type inside a group) reshapes its frame by the matrix and its text reflows at its size, as a bounding-box handle drag does (default: the type transforms too)",
|
||||
"{matrix: [a,b,c,d,e,f], copy?: bool, ids?, strokes?: bool, corners?: bool, typeAreas?: bool, anchors?: bool, objects?: bool (Transform Objects, default true; false: the art stays and, with patterns, only its pattern tiles transform), patterns?: bool (Transform Patterns: pattern fills and strokes transform with the art; default: prefs transformPatternTiles), releaseOutside?: bool} apply an affine to the selection (or ids); anchors (without ids or copy): paths with anchors selected with Direct Selection have only those anchors and their handles transformed, as the Transform tools and object.move/rotate/scale/reflect/shear do (default: the whole objects); strokes/corners: Scale Strokes & Effects / Scale Corners (default: the preferences); typeAreas: area type among them (not type inside a group) reshapes its frame by the matrix and its text reflows at its size, as a bounding-box handle drag does (default: the type transforms too); releaseOutside (without copy or anchors): a Shaper Group's original shape that ends wholly outside the bounds the group's original shapes had before takes shaper.releaseSource in the same undo step, named Remove from Shaper Group, as the Selection tool's moves in Construction mode do",
|
||||
has_doc,
|
||||
transform
|
||||
),
|
||||
|
||||
@@ -235,13 +235,40 @@ fn resize_type_area(n: &mut Node, xf: Affine) -> bool {
|
||||
|
||||
pub(super) fn transform(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
check_switches(p, &TRANSFORM_SWITCHES, "object.transform")?;
|
||||
check_switches(p, &["anchors"], "object.transform")?;
|
||||
check_switches(p, &["anchors", "releaseOutside"], "object.transform")?;
|
||||
let m = matrix_param(p, "matrix").ok_or_else(|| bad("object.transform", "missing matrix [a,b,c,d,e,f]"))?;
|
||||
let (ids, anchors) = match ids_param(p, "ids") {
|
||||
Some(v) => (outermost(&s.doc()?.doc, v), false),
|
||||
None => (selected_roots_to_transform(s)?, bool_or(p, "anchors", false)),
|
||||
};
|
||||
apply_transform(s, "Transform", ids, m, p, anchors)
|
||||
// Shaper's Construction mode: an original shape moved wholly outside its group's bounds leaves
|
||||
// the group.
|
||||
let moved = if bool_or(p, "releaseOutside", false) && !bool_or(p, "copy", false) && !anchors {
|
||||
crate::cmd::shaper::moving_sources(s, &ids)?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
// Outside a drag and an undo group, the move and the removal are one undo step, named for the
|
||||
// removal when there is one.
|
||||
let grouped = !moved.is_empty() && s.doc()?.interaction.is_none() && s.doc()?.undo_group.is_none();
|
||||
if grouped {
|
||||
s.begin_named_undo_group(None);
|
||||
}
|
||||
let r = apply_transform(s, "Transform", ids, m, p, anchors);
|
||||
let released = match &r {
|
||||
Ok(_) if !moved.is_empty() => crate::cmd::shaper::release_outside(s, &moved),
|
||||
_ => Ok(false),
|
||||
};
|
||||
if grouped && let Some(st) = s.active_mut() {
|
||||
st.undo_group = None;
|
||||
if matches!(released, Ok(true))
|
||||
&& let Some(e) = st.history.undo.last_mut()
|
||||
{
|
||||
e.label = "Remove from Shaper Group".into();
|
||||
}
|
||||
}
|
||||
released?;
|
||||
r
|
||||
}
|
||||
|
||||
pub(super) fn move_cmd(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
|
||||
Reference in New Issue
Block a user