From 411787afb28193058822df5cbfa0fa86f2dd9e78 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Wed, 3 Jun 2026 21:37:51 +0800 Subject: [PATCH] docs(automation): add view.select client wrapper, example usage, and docs --- doc/automation.md | 29 +++++++++++++++++++++++++++-- tools/automation/example_slice.py | 7 ++++--- tools/automation/orca_automation.py | 9 +++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/doc/automation.md b/doc/automation.md index 8e592a7e14..c1ac04079c 100644 --- a/doc/automation.md +++ b/doc/automation.md @@ -95,7 +95,7 @@ when the request body cannot be parsed as JSON, the response `id` is `null`. ## 4. Methods -There are 11 methods. Capabilities advertised by `automation.version` list the 10 +There are 12 methods. Capabilities advertised by `automation.version` list the 11 callable feature methods (every method except `automation.version` itself). ### `automation.version` @@ -110,7 +110,8 @@ Returns server identity and the list of supported methods. Takes no parameters. "protocol": "2.0", "capabilities": [ "tree.dump", "tree.find", "widget.get", "input.click", "input.type", - "input.key", "sync.wait_for", "app.state", "screenshot.window", "file.open" + "input.key", "sync.wait_for", "app.state", "screenshot.window", "file.open", + "view.select" ] } ``` @@ -329,6 +330,30 @@ added to the scene (`load_files(...).size()`). - `1004` (GUI busy) — the GUI-thread marshal timed out. An extremely large model can exceed the marshal timeout and surface here; documented, not mitigated in v1. +### `view.select` + +Switch the main window to a top-level view/tab at runtime. Useful to put the UI in a +known state before other actions — e.g. switch to **Prepare** before loading a model, +or to **Preview** after slicing. + +**Params:** + +| Param | Type | Required | Meaning | +|---|---|---|---| +| `view` | string | yes | The target view. One of: `home`, `prepare` (3D editor), `preview` (sliced G-code), `device`, `multi_device`, `project`, `calibration`. | + +**Result:** `{ "ok": true, "view": , "index": }`, where `index` is the +resulting tab index (it can vary with layout, since some tabs — e.g. `multi_device` — +are only present in certain configurations). + +**Errors:** + +- `-32602` (invalid params) — `view` is missing, is not a string, or is empty. +- `1001` (not found) — the view name is unknown, or that view is not available in the + current layout (for example `prepare`/`preview` in G-code-viewer mode, or + `multi_device` when multi-device is disabled). +- `1004` (GUI busy) — the GUI-thread marshal timed out. + --- ## 5. Unified node shape diff --git a/tools/automation/example_slice.py b/tools/automation/example_slice.py index 384dcb4cfb..da1a977519 100644 --- a/tools/automation/example_slice.py +++ b/tools/automation/example_slice.py @@ -42,9 +42,10 @@ def main() -> int: print("ERROR: automation server did not start", file=sys.stderr) return 1 - # Load the model into the already-running instance, then wait until the - # project reports loaded. file.open is synchronous, so project_loaded is - # already true on return; the wait is a belt-and-suspenders guard. + # Switch to the Prepare (3D editor) view first, then load the model into the + # already-running instance. file.open is synchronous, so project_loaded is + # already true on return; the wait below is a belt-and-suspenders guard. + orca.select_view("prepare") orca.open([args.model]) deadline = time.time() + 30 while time.time() < deadline: diff --git a/tools/automation/orca_automation.py b/tools/automation/orca_automation.py index 4dbd81fb8b..f4eac80206 100644 --- a/tools/automation/orca_automation.py +++ b/tools/automation/orca_automation.py @@ -91,6 +91,15 @@ class OrcaClient: paths = [paths] return self._call("file.open", {"paths": list(paths)}) + def select_view(self, view) -> dict: + """Switch the main window to a top-level view/tab by name. + + `view` is one of: "home", "prepare", "preview", "device", + "multi_device", "project", "calibration". Returns + {"ok": True, "view": , "index": }. Raises OrcaError 1001 if the + view name is unknown or not available in the current layout.""" + return self._call("view.select", {"view": view}) + def wait_for(self, target: dict, state: str = "visible", value: Optional[str] = None, timeout_ms: int = 5000, poll_ms: int = 100) -> dict: