layerMoveCommand function
The one command that moves keys to layer (spec 12b D12), or null
when every member is already on it. Read from doc as it is now.
Per key:
- a root entity:
SetEntityLayerCommand; a drafted region moves every record of it — from a fill, its boundary and every fill naming that boundary; from a boundary, every fill infills.fillsOf(boundary); - an ATTRIB: its owning instance, which then moves as below;
- an instance:
SetInstanceLayerCommand; - a parametric object:
SetComponentCommand<ObjectLayer>.
Each member is moved once — the entity records first, then the
instances, then the objects, each in key order; a member already on layer
(exact == on the stored value; an object without an ObjectLayer is
on layer 0) is skipped. One member left is its command alone; more are
one CompoundCommand: one undo step either way. A plain group is not a
member (the picker is disabled for it, layerPickerBlocked).
Implementation
DraftCommand? layerMoveCommand(
DraftDocument doc, Iterable<SelectionKey> keys, Handle layer) {
final entities = <Handle>{};
final instances = <Handle>{};
final objects = <Handle>{};
final store = doc.entities;
for (final k in keys) {
final h = k.target;
final node = doc.tree[h];
if (node is InstanceNode) {
instances.add(h);
continue;
}
if (node is GroupNode) {
if (isParametricObject(doc, h)) objects.add(h);
continue;
}
if (node != null) continue;
final slot = store.slotOf(h);
if (slot == null) continue;
if (_owningInstance(doc, slot) case final owner?) {
instances.add(owner.handle);
continue;
}
final boundary = _boundaryOfFill(doc, slot) ?? h;
entities
..add(boundary)
..addAll(doc.fills.fillsOf(boundary));
if (boundary != h) entities.add(h);
}
final commands = <DraftCommand>[
for (final e in entities)
if (store.layerAt(store.slotOf(e)!) != layer)
SetEntityLayerCommand(e, layer),
for (final i in instances)
if ((doc.tree[i]! as InstanceNode).layer != layer)
SetInstanceLayerCommand(i, layer),
for (final o in objects)
if ((doc.components.get<ObjectLayer>(o)?.layer ??
ReservedHandles.layerZero) !=
layer)
SetComponentCommand<ObjectLayer>(o, ObjectLayer(layer)),
];
return switch (commands.length) {
0 => null,
1 => commands.single,
_ => CompoundCommand(commands, label: 'Move to layer'),
};
}