mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 04:07:12 -06:00
MCP: select.key checks its id, and agents can read the key object
Agents could set and clear the key object but not read it: document.inspect, the control channel's ui.pointer reply and the headless pointer_gesture reply left it out, and select.key returned null. select.key with an id that was not selected, or with a value that is not an id, such as "x", cleared the key without an error. A compound-path member or an object inside a selected group could become the key. select.key now checks its id as select.set, select.add and select.toggle do (#784). It returns an error for an id that is not a selected top-level object and leaves the key as it was. Layers, compound-path members and objects inside another selected object are not top-level objects. select.key {id: null} used to clear the key and is now an error; select.key {} still clears it. select.key returns {key}, and document.inspect and both pointer replies include the key object as "key". In isolation mode a Selection-tool click can pick an object that select.key does not accept as the key: a sublayer inside an isolated layer, a member inside an isolated compound path, or an object in an isolated group that is also selected. The tool no longer sends select.key {id} for such an object. When the object is already the key, the tool still sends select.key {}, which clears the key. A recorded action whose select.key step names an object that is not a selected top-level object when the action plays now fails and is rolled back, as an action with a select.set step naming a deleted object has failed since #784. Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
This commit is contained in:
@@ -65,7 +65,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Set Key Object",
|
||||
[],
|
||||
None,
|
||||
"{id?: a selected object, one of two or more (the Selection tool: a click on one object of a selection of several; on the key again: none)} the key object Align aligns to and Distribute Spacing spaces from; none clears it, as does a selection that holds only the key and objects inside it (one object, or a group key and its own members)",
|
||||
"{id?: a selected top-level object (not a layer, a compound-path member or an object inside another selected object), one of two or more (the Selection tool: a click on one object of a selection of several; on the key again: no id)} the key object Align aligns to and Distribute Spacing spaces from; without `id` it clears the key, as does a selection that holds only the key and objects inside it (one object, or a group key and its own members); any other id is an error that leaves the key as it was → {key} (the resulting key object, or null)",
|
||||
has_doc,
|
||||
key
|
||||
),
|
||||
@@ -297,9 +297,18 @@ fn selection_result(s: &Session) -> Result<Value> {
|
||||
}
|
||||
|
||||
fn key(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let id = id_param(p, "id");
|
||||
s.select(|_, sel| sel.key = id.filter(|i| sel.contains(*i)))?;
|
||||
ok()
|
||||
let id = p.get("id").map(|value| checked_id(s, value, "select.key")).transpose()?;
|
||||
if let Some(id) = id {
|
||||
let st = s.doc()?;
|
||||
// A selected top-level object is the only top-level object among the selected ones of
|
||||
// itself and its ancestors.
|
||||
let selected = st.doc.ancestry(id).unwrap_or_default().into_iter().filter(|a| st.selection.contains(*a)).collect();
|
||||
if super::edit::roots_of(&st.doc, selected) != [id] {
|
||||
return Err(bad("select.key", format!("object {id} is not a selected top-level object")));
|
||||
}
|
||||
}
|
||||
s.select(|_, sel| sel.key = id)?;
|
||||
Ok(json!({ "key": s.doc()?.selection.key }))
|
||||
}
|
||||
|
||||
/// `[[subpath, anchor]…]` anchor references of `cmd`: a malformed entry fails rather than being
|
||||
|
||||
Reference in New Issue
Block a user