mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-22 16:32:40 +00:00
orca.host.ui.create_dock_panel(html, title, width, height, on_message, on_close, dock) hosts plugin HTML in a pane of the Plater's dock manager, next to the sidebar, and returns a UiDockPanel handle (post/show/hide/close/is_open). The arguments follow create_window(). The panel uses the window.orca bridge of plugin windows, restores its position and size from the saved window layout, hides with the Plater off the Prepare and Preview tabs when floating, and is closed with its plugin; plugin panes are removed in MainFrame::shutdown(). The web view hosting moves out of PluginPage into a shared WebPanel base: bootstrap page and swap to the plugin HTML, theme, element-default and bridge scripts, window.orca message parsing, delivery to the page, and live re-theming, also re-applied on every load after the swap. Pages tabs and docked panels both derive from it. Pages tabs now re-theme in place on a theme change instead of being reloaded, and a window.orca call a host does not support is logged. What the hosts share no longer lives in one of them: the bootstrap page, the base URL and the plugin-window bridge move to Widgets/WebHosting, used by WebDialog and WebPanel alike. The Plater restores plugin panes with a new saved-layout parser, GUI/AuiPaneLayout, kept in its own small header so slic3rutils can test it without pulling in the Plater. The web hosting classes carry no plugin name, so other hosts can reuse them: PluginWebDialog becomes WebDialog (its bootstrap page moves to resources/web/dialog/WebDialog), and destroy_for_plugin(), load_plugin_content() and plugin_defaults_user_script() become destroy_silently(), load_page_html() and element_defaults_user_script(). Includes a sample plugin (sandboxes/orca_dock_panel_plugin_any.py) and binding and layout-helper tests in slic3rutils.
147 lines
4.9 KiB
Python
147 lines
4.9 KiB
Python
# /// script
|
|
# requires-python = ">=3.12"
|
|
#
|
|
# [tool.orcaslicer.plugin]
|
|
# name = "Dock Panel Demo"
|
|
# description = "Opens a dockable panel beside the 3D view that lists the objects on the plate."
|
|
# author = "OrcaSlicer"
|
|
# version = "0.0.1"
|
|
# ///
|
|
"""Dock Panel Demo -- orca.host.ui.create_dock_panel().
|
|
|
|
Run it from the Plugins dialog. It opens an HTML panel docked on the right of the 3D view, in the
|
|
same dock area as the sidebar. Drag its caption to dock it on another side (or float it, where the
|
|
platform allows), hide it from the page and run the plugin again to bring it back, or close it with
|
|
its close button or from the page.
|
|
|
|
page --orca.postMessage({command: 'refresh'})--> plugin.on_message()
|
|
page --orca.postMessage({command: 'hide'})--> plugin.on_message() -> panel.hide()
|
|
page --orca.close()--> panel closes, plugin.on_close()
|
|
plugin --panel.post({command: 'objects', ...})--> page (orca.onMessage)
|
|
"""
|
|
import orca
|
|
|
|
PAGE = """
|
|
<style>
|
|
body { margin: 0; padding: 12px; font-size: 13px; }
|
|
h3 { margin: 0 0 4px; font-size: 14px; }
|
|
.note { margin: 0 0 12px; color: var(--orca-muted); font-size: 12px; }
|
|
.actions { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
|
|
.actions button.quiet { background: transparent; color: var(--orca-fg); border-color: var(--orca-border); }
|
|
table { width: 100%; border-collapse: collapse; }
|
|
td.count { text-align: right; font-variant-numeric: tabular-nums; }
|
|
#status { margin-top: 10px; color: var(--orca-muted); font-size: 12px; }
|
|
</style>
|
|
|
|
<h3>Objects on the plate</h3>
|
|
<p class="note">Docked beside the 3D view. Drag the caption to move it.</p>
|
|
|
|
<div class="actions">
|
|
<button type="button" id="refresh">Refresh</button>
|
|
<button type="button" id="hide" class="quiet">Hide</button>
|
|
<button type="button" id="close" class="quiet">Close</button>
|
|
</div>
|
|
|
|
<table>
|
|
<thead><tr><th>Name</th><th>Parts</th><th>Copies</th></tr></thead>
|
|
<tbody id="rows"></tbody>
|
|
</table>
|
|
<p id="status">Waiting for the plugin...</p>
|
|
|
|
<script>
|
|
(function () {
|
|
function text(value) {
|
|
var span = document.createElement("span");
|
|
span.textContent = value;
|
|
return span.innerHTML;
|
|
}
|
|
|
|
function render(message) {
|
|
var rows = document.getElementById("rows");
|
|
var status = document.getElementById("status");
|
|
if (message.error) {
|
|
rows.innerHTML = "";
|
|
status.textContent = message.error;
|
|
return;
|
|
}
|
|
rows.innerHTML = message.objects.map(function (object) {
|
|
return "<tr><td>" + text(object.name) + "</td><td class=\\"count\\">" + object.volumes +
|
|
"</td><td class=\\"count\\">" + object.instances + "</td></tr>";
|
|
}).join("");
|
|
status.textContent = message.objects.length + " object(s), refreshed " + new Date().toLocaleTimeString();
|
|
}
|
|
|
|
orca.onMessage(function (message) {
|
|
if (message && message.command === "objects")
|
|
render(message);
|
|
});
|
|
|
|
document.getElementById("refresh").addEventListener("click", function () {
|
|
orca.postMessage({ command: "refresh" });
|
|
});
|
|
document.getElementById("hide").addEventListener("click", function () {
|
|
orca.postMessage({ command: "hide" });
|
|
});
|
|
document.getElementById("close").addEventListener("click", function () {
|
|
orca.close();
|
|
});
|
|
|
|
orca.postMessage({ command: "refresh" });
|
|
})();
|
|
</script>
|
|
"""
|
|
|
|
|
|
def plate_objects():
|
|
try:
|
|
model = orca.host.model()
|
|
except RuntimeError as error:
|
|
return {"command": "objects", "error": str(error)}
|
|
return {
|
|
"command": "objects",
|
|
"objects": [
|
|
{"name": obj.name or "(unnamed)", "volumes": obj.volume_count(), "instances": obj.instance_count()}
|
|
for obj in model.objects()
|
|
],
|
|
}
|
|
|
|
|
|
class DockPanelDemo(orca.script.ScriptPluginCapabilityBase):
|
|
panel = None
|
|
|
|
def get_name(self):
|
|
return "Dock Panel Demo"
|
|
|
|
def execute(self):
|
|
# The capability instance lives as long as the plugin, so a second run finds the open panel.
|
|
if self.panel is not None and self.panel.is_open():
|
|
self.panel.show()
|
|
return orca.ExecutionResult.success("Dock Panel Demo is already open.")
|
|
self.panel = orca.host.ui.create_dock_panel(
|
|
html=PAGE,
|
|
title="Dock Panel Demo",
|
|
width=320,
|
|
height=480,
|
|
on_message=self.on_message,
|
|
on_close=self.on_close,
|
|
dock="right",
|
|
)
|
|
return orca.ExecutionResult.success("Dock Panel Demo opened.")
|
|
|
|
# Called on the UI thread when the page posts.
|
|
def on_message(self, message):
|
|
command = (message or {}).get("command")
|
|
if command == "refresh":
|
|
self.panel.post(plate_objects())
|
|
elif command == "hide":
|
|
self.panel.hide()
|
|
|
|
def on_close(self):
|
|
self.panel = None
|
|
|
|
|
|
@orca.plugin
|
|
class DockPanelDemoPlugin(orca.base):
|
|
def register_capabilities(self):
|
|
orca.register_capability(DockPanelDemo)
|