ocs_doc_api: layer CRUD, per-curve layer assignment, XDATA/XRECORD support, and bulk SetXDataMany

This commit is contained in:
Sebastian committed 2026-09-10 10:43:15 +02:00
1 parent b19992cbcb
commit 8bf5eac3fc
27 files changed
+3340 -181

No files matched your search

@@ -192,6 +192,32 @@ Table: create_table(insertion_point, data[row][col]) builds rows x columns of te
- **create_table**(insertion_point: [f64; 3], data: &[Vec<String>]) -> `Entity` — `CreateTable`
## `XRecord` (acadrust `XRecord`, collection `entities`)
Extended record (XRecord): arbitrary DXF group-code/value pairs. Roundtripped verbatim as an XRecordSpec payload.
### Constructors (`doc.entities()`)
- **create_xrecord**(spec: XRecordSpec) -> `Entity` — `CreateXRecord`
### Methods
- **payload**() -> `XRecordSpec` — query `GetXRecord`
- **set_payload**(spec: XRecordSpec) -> `()` — op `SetXRecord`
- **xdata**(application_name: &str) -> `Option<XDataRecord>` — query `GetXData`
- **set_xdata**(application_name: &str, record: Option<XDataRecord>) -> `()` — op `SetXData`
## `Layer` (acadrust `-`, collection `layers`)
Named drawing layer (color, linetype, lineweight, visibility). Not an entity handle; accessed through Document::layers().
### Methods
- **list**() -> `Vec<LayerInfo>` — query `ListLayers`
- **create**(info: LayerInfo) -> `()` — op `CreateLayer`
- **update**(name: String, info: LayerInfo) -> `()` — op `UpdateLayer`
- **delete**(name: String) -> `()` — op `DeleteLayer`
## Generic methods (every handle)
Every typed handle (`Solid`, `Line`, `Circle`, `Polyline`, `Point`, `ArcCurve`,
@@ -204,10 +230,32 @@ Every typed handle (`Solid`, `Line`, `Circle`, `Polyline`, `Point`, `ArcCurve`,
- **`transform(placement)`** — in-place rigid similarity (same `ObjectId`). **v1:
solids only.**
- **`delete()`** — remove the entity (one undo step).
- **`layer()` -> `String`** — the name of the layer the entity is on.
- **`set_layer(layer)`** — move the entity to an existing layer (one undo step;
blocked if the entity or target layer is locked).
`Entity` additionally has `view()` (id + kind + bounds) and `as_solid()` (typed
downcast when `kind == "Solid3D"`).
## Layer table
Layers are a named document table, not an entity family. `Document::layers()`
lists all layers as `Vec<LayerInfo>`. Table-level ops are `CreateLayer(info)`,
`UpdateLayer { name, info }` and `DeleteLayer { name }`. `Entity::layer()`
returns the layer name and `Entity::set_layer(layer)` moves the entity to an
existing layer. The host rejects duplicate names, deletion of layer "0" or the
current layer, and removing a layer that still has entities assigned.
## Transports
- **`InProcess`** (feature `host`) — drives a `DocApiBackend` directly in the host.
- **`OcsPluginApiIpc`** (feature `ipc`) — serializes envelopes over the
`ocs_plugin_api` `PluginRequestSender`/`PluginRequest` channel. The host routes
`DocApiRequest { tab_id, bytes }` to the same executor.
- **`doc_api_for_host(host)`** (feature `doc_api_host`) — convenience helper that
builds a `DocApi` from any `ocs_plugin_api::host::HostApi` exposing a
`PluginRequestSender` (out-of-process / worker-thread plugins).
## Collections & cross-cutting
- **`DocApi`** — root: `document(tab)`, `active_tab()`, `alive()`.
@@ -284,6 +332,14 @@ Every `Operation` is ONE atomic write op (one undo step); every `Query` is read-
- `CreateAttributeDefinition(AttributeDefinitionSpec)`
- `CreateTable(TableSpec)`
- `CreateDimensionAngular2Ln(DimensionAngularSpec)`
- `SetXData { id: ObjectId, application_name: String, record: Option<XDataRecord> }`
- `CreateXRecord(XRecordSpec)`
- `SetXRecord { id: ObjectId, spec: XRecordSpec }`
- `CreateLayer(LayerInfo)`
- `UpdateLayer { name: String, info: LayerInfo }`
- `DeleteLayer { name: String }`
- `SetEntityLayer { id: ObjectId, layer: String }`
- `SetXDataMany(Vec<(ObjectId, String, Option<XDataRecord)>)`
### `Query`
@@ -299,6 +355,10 @@ Every `Operation` is ONE atomic write op (one undo step); every `Query` is read-
- `GetAttributes { id: ObjectId }`
- `GetBlockEntities { block_name: String }`
- `GetViewportView { id: ObjectId }`
- `GetXData { id: ObjectId, application_name: String }`
- `GetXRecord { id: ObjectId }`
- `ListLayers`
- `GetEntityLayer { id: ObjectId }`
## Errors (`ApiError`)
+175 -3
View File
@@ -1124,6 +1124,164 @@
"handle": "Entity",
"methods": [],
"name": "Table"
},
{
"acadrust_variant": "XRecord",
"collection": "entities",
"constructors": [
{
"args": [
{
"name": "spec",
"ty": "XRecordSpec"
}
],
"bulk": false,
"fixed": null,
"name": "create_xrecord",
"op": "CreateXRecord",
"returns": "Entity"
}
],
"handle": "XRecord",
"methods": [
{
"args": [],
"bulk": false,
"fixed": null,
"kind": "query",
"name": "payload",
"op": null,
"query": "GetXRecord",
"read_only": true,
"returns": "XRecordSpec"
},
{
"args": [
{
"name": "spec",
"ty": "XRecordSpec"
}
],
"bulk": false,
"fixed": null,
"kind": "op",
"name": "set_payload",
"op": "SetXRecord",
"query": null,
"read_only": false,
"returns": "()"
},
{
"args": [
{
"name": "application_name",
"ty": "&str"
}
],
"bulk": false,
"fixed": null,
"kind": "query",
"name": "xdata",
"op": null,
"query": "GetXData",
"read_only": true,
"returns": "Option<XDataRecord>"
},
{
"args": [
{
"name": "application_name",
"ty": "&str"
},
{
"name": "record",
"ty": "Option<XDataRecord>"
}
],
"bulk": false,
"fixed": null,
"kind": "op",
"name": "set_xdata",
"op": "SetXData",
"query": null,
"read_only": false,
"returns": "()"
}
],
"name": "XRecord"
},
{
"acadrust_variant": null,
"collection": "layers",
"constructors": [],
"handle": "Layer",
"methods": [
{
"args": [],
"bulk": false,
"fixed": null,
"kind": "query",
"name": "list",
"op": null,
"query": "ListLayers",
"read_only": true,
"returns": "Vec<LayerInfo>"
},
{
"args": [
{
"name": "info",
"ty": "LayerInfo"
}
],
"bulk": false,
"fixed": null,
"kind": "op",
"name": "create",
"op": "CreateLayer",
"query": null,
"read_only": false,
"returns": "()"
},
{
"args": [
{
"name": "name",
"ty": "String"
},
{
"name": "info",
"ty": "LayerInfo"
}
],
"bulk": false,
"fixed": null,
"kind": "op",
"name": "update",
"op": "UpdateLayer",
"query": null,
"read_only": false,
"returns": "()"
},
{
"args": [
{
"name": "name",
"ty": "String"
}
],
"bulk": false,
"fixed": null,
"kind": "op",
"name": "delete",
"op": "DeleteLayer",
"query": null,
"read_only": false,
"returns": "()"
}
],
"name": "Layer"
}
],
"layouts": {
@@ -1164,7 +1322,15 @@
"CreateDimensionAngular(DimensionAngularSpec)",
"CreateAttributeDefinition(AttributeDefinitionSpec)",
"CreateTable(TableSpec)",
"CreateDimensionAngular2Ln(DimensionAngularSpec)"
"CreateDimensionAngular2Ln(DimensionAngularSpec)",
"SetXData { id: ObjectId, application_name: String, record: Option<XDataRecord> }",
"CreateXRecord(XRecordSpec)",
"SetXRecord { id: ObjectId, spec: XRecordSpec }",
"CreateLayer(LayerInfo)",
"UpdateLayer { name: String, info: LayerInfo }",
"DeleteLayer { name: String }",
"SetEntityLayer { id: ObjectId, layer: String }",
"SetXDataMany(Vec<(ObjectId, String, Option<XDataRecord)>)"
]
},
"Query": {
@@ -1180,7 +1346,11 @@
"GetDimensionMeasurement { id: ObjectId }",
"GetAttributes { id: ObjectId }",
"GetBlockEntities { block_name: String }",
"GetViewportView { id: ObjectId }"
"GetViewportView { id: ObjectId }",
"GetXData { id: ObjectId, application_name: String }",
"GetXRecord { id: ObjectId }",
"ListLayers",
"GetEntityLayer { id: ObjectId }"
]
}
},
@@ -1205,7 +1375,9 @@
"XLine",
"Text",
"MText",
"Dimension"
"Dimension",
"XRecord",
"Layer"
],
"root": "DocApi"
},
+14 -2
View File
@@ -29,7 +29,15 @@
"CreateDimensionAngular(DimensionAngularSpec)",
"CreateAttributeDefinition(AttributeDefinitionSpec)",
"CreateTable(TableSpec)",
"CreateDimensionAngular2Ln(DimensionAngularSpec)"
"CreateDimensionAngular2Ln(DimensionAngularSpec)",
"SetXData { id: ObjectId, application_name: String, record: Option<XDataRecord> }",
"CreateXRecord(XRecordSpec)",
"SetXRecord { id: ObjectId, spec: XRecordSpec }",
"CreateLayer(LayerInfo)",
"UpdateLayer { name: String, info: LayerInfo }",
"DeleteLayer { name: String }",
"SetEntityLayer { id: ObjectId, layer: String }",
"SetXDataMany(Vec<(ObjectId, String, Option<XDataRecord)>)"
]
},
"Query": {
@@ -45,7 +53,11 @@
"GetDimensionMeasurement { id: ObjectId }",
"GetAttributes { id: ObjectId }",
"GetBlockEntities { block_name: String }",
"GetViewportView { id: ObjectId }"
"GetViewportView { id: ObjectId }",
"GetXData { id: ObjectId, application_name: String }",
"GetXRecord { id: ObjectId }",
"ListLayers",
"GetEntityLayer { id: ObjectId }"
]
}
}
+26 -1
View File
@@ -10,7 +10,7 @@ use crate::id::ObjectId;
use crate::ops::{
AttributeDefinitionSpec, BoolOp, Curve2Spec, DimensionAngularSpec, DimensionRadialSpec,
DimensionSpec, EntitySpec, HatchSpec, InsertSpec, MTextSpec, PlacementSpec, RasterImageSpec,
SolidPrimitive, TableSpec, TextSpec, ViewportSpec,
SolidPrimitive, TableSpec, TextSpec, ViewportSpec, XDataRecord, XRecordSpec,
};
/// A typed write operation. Each variant is ONE atomic host call = one
@@ -99,4 +99,29 @@ pub enum Operation {
CreateTable(TableSpec),
// dimension sub-types (2-line angular)
CreateDimensionAngular2Ln(DimensionAngularSpec),
// xdata / xrecord roundtrip
SetXData {
id: ObjectId,
application_name: String,
record: Option<XDataRecord>,
},
SetXDataMany(Vec<(ObjectId, String, Option<XDataRecord>)>),
CreateXRecord(XRecordSpec),
SetXRecord {
id: ObjectId,
spec: XRecordSpec,
},
// layer CRUD
CreateLayer(crate::ops::LayerInfo),
UpdateLayer {
name: String,
info: crate::ops::LayerInfo,
},
DeleteLayer {
name: String,
},
SetEntityLayer {
id: ObjectId,
layer: String,
},
}
+31
View File
@@ -55,4 +55,35 @@ pub enum Query {
GetViewportView {
id: ObjectId,
},
/// The XDATA record for `application_name` attached to an entity (`None` if absent).
GetXData {
id: ObjectId,
application_name: String,
},
/// The XRECORD object payload by id.
GetXRecord {
id: ObjectId,
},
/// List all layers in the document.
ListLayers,
/// The layer name of an entity.
GetEntityLayer {
id: ObjectId,
},
/// Enumerate first-class entities, optionally filtered by kind and/or layer.
/// `include_bounds` populates `EntityView::bounds`; leave it false for a
/// lightweight list view.
EnumerateEntities {
kind: Option<String>,
layer: Option<String>,
include_bounds: bool,
},
/// The WCS location of a Point entity.
GetPointPosition {
id: ObjectId,
},
/// The start and end WCS points of a Line entity.
GetLineGeometry {
id: ObjectId,
},
}