forked from 1b-agent/opencadstudio-upstream
feat(python): validated, undoable layer table (doc.layers)
Adds the additive v7 TableOperation request and HostApi::table_operation for layer create/modify/rename/delete/set-current. Refusals are decided before the undo step is recorded. Python wrapper, real-IPC audit with DWG/DXF persistence, IPC round-trip test, Python unit test and docs. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
6b8056cfeb
commit
b7b6e2cef5
12 files changed
+681
No files matched your search
@@ -199,9 +199,91 @@ class _Solids:
|
||||
return self.transform(entity, ocs.mirror_matrix(index, [float(v) for v in about]))
|
||||
|
||||
|
||||
class _Layers:
|
||||
"""The drawing's layer table. Every change goes through the host: it is
|
||||
validated, becomes one undo step, and a refusal raises `RuntimeError`
|
||||
without changing the drawing."""
|
||||
|
||||
_KEYS = ("color", "linetype", "lineweight", "off", "frozen", "locked",
|
||||
"plottable", "transparency", "description")
|
||||
|
||||
def _records(self):
|
||||
return ocs.layer_records()
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._records())
|
||||
|
||||
def __len__(self):
|
||||
return len(self._records())
|
||||
|
||||
def __contains__(self, name):
|
||||
wanted = str(name).strip().upper()
|
||||
return any(r["name"].upper() == wanted for r in self._records())
|
||||
|
||||
def __getitem__(self, name):
|
||||
wanted = str(name).strip().upper()
|
||||
for record in self._records():
|
||||
if record["name"].upper() == wanted:
|
||||
return record
|
||||
raise KeyError(name)
|
||||
|
||||
def get(self, name, default=None):
|
||||
try:
|
||||
return self[name]
|
||||
except KeyError:
|
||||
return default
|
||||
|
||||
def names(self):
|
||||
return [r["name"] for r in self._records()]
|
||||
|
||||
@property
|
||||
def current(self):
|
||||
for record in self._records():
|
||||
if record["current"]:
|
||||
return record
|
||||
return None
|
||||
|
||||
@current.setter
|
||||
def current(self, name):
|
||||
self.set_current(name)
|
||||
|
||||
def _options(self, properties):
|
||||
unknown = [k for k in properties if k not in self._KEYS]
|
||||
if unknown:
|
||||
raise TypeError("unknown layer propert%s: %s" % ("y" if len(unknown) == 1 else "ies", ", ".join(sorted(unknown))))
|
||||
return {k: v for k, v in properties.items() if v is not None}
|
||||
|
||||
def create(self, name, **properties):
|
||||
"""Create a layer and return its record. `color` is an ACI index
|
||||
(1-255), an (r, g, b) tuple or a Color dict; `lineweight` is in
|
||||
1/100 mm (-1 ByLayer, -2 ByBlock, -3 Default); `transparency` is a
|
||||
percentage 0-90."""
|
||||
ocs.layer_operation("create", str(name), self._options(properties))
|
||||
return self[name]
|
||||
|
||||
def modify(self, name, **properties):
|
||||
"""Change only the properties given and return the updated record."""
|
||||
ocs.layer_operation("modify", str(name), self._options(properties))
|
||||
return self[name]
|
||||
|
||||
def rename(self, name, new_name):
|
||||
ocs.layer_operation("rename", str(name), {"to": str(new_name)})
|
||||
return self[new_name]
|
||||
|
||||
def delete(self, name, erase_objects=False):
|
||||
"""Delete a layer. A layer that still holds objects is refused unless
|
||||
`erase_objects=True`. Layer 0, Defpoints and the current layer stay."""
|
||||
ocs.layer_operation("delete", str(name), {"erase_objects": bool(erase_objects)})
|
||||
|
||||
def set_current(self, name):
|
||||
ocs.layer_operation("set_current", str(name), None)
|
||||
return self[name]
|
||||
|
||||
|
||||
class _Document:
|
||||
def __init__(self):
|
||||
self._pending = None
|
||||
self.layers = _Layers()
|
||||
self.entities = _Entities(self)
|
||||
self.solids = _Solids(self)
|
||||
|
||||
|
||||
Reference in new issue
Block a user