Spaces:
Sleeping
Sleeping
jdegenstein
commited on
Create cadviewer.py
Browse files- cadviewer.py +121 -0
cadviewer.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
nicegui cadviewer
|
| 3 |
+
|
| 4 |
+
name: cadviewer.py
|
| 5 |
+
by: jdegenstein
|
| 6 |
+
date: January 24, 2025
|
| 7 |
+
|
| 8 |
+
desc:
|
| 9 |
+
|
| 10 |
+
This module creates a graphical window with a text editor and CAD viewer (based on ocp_vscode).
|
| 11 |
+
The graphical user interface is based on nicegui and spawns the necessary subprocess and allows
|
| 12 |
+
for re-running the user-supplied script and displaying the results.
|
| 13 |
+
|
| 14 |
+
Key Features:
|
| 15 |
+
- Has a run button for executing user code
|
| 16 |
+
- Has a keyboard shortcut of CTRL-Enter to run the user code
|
| 17 |
+
|
| 18 |
+
license:
|
| 19 |
+
|
| 20 |
+
Copyright 2025 jdegenstein
|
| 21 |
+
|
| 22 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 23 |
+
you may not use this file except in compliance with the License.
|
| 24 |
+
You may obtain a copy of the License at
|
| 25 |
+
|
| 26 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 27 |
+
|
| 28 |
+
Unless required by applicable law or agreed to in writing, software
|
| 29 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 30 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 31 |
+
See the License for the specific language governing permissions and
|
| 32 |
+
limitations under the License.
|
| 33 |
+
|
| 34 |
+
"""
|
| 35 |
+
|
| 36 |
+
from nicegui import app, ui
|
| 37 |
+
from nicegui.events import KeyEventArguments
|
| 38 |
+
import subprocess
|
| 39 |
+
|
| 40 |
+
app.native.window_args["resizable"] = True
|
| 41 |
+
app.native.start_args["debug"] = True
|
| 42 |
+
# app.native.settings['ALLOW_DOWNLOADS'] = True # export "downloads" ?
|
| 43 |
+
app.native.settings["MATPLOTLIB"] = False
|
| 44 |
+
|
| 45 |
+
editor_fontsize = 18
|
| 46 |
+
# TODO: consider separate editor execution thread from nicegui thread
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
# run ocp_vscode in a subprocess
|
| 50 |
+
def startup_all():
|
| 51 |
+
global ocpcv_proc
|
| 52 |
+
# spawn separate viewer process
|
| 53 |
+
ocpcv_proc = subprocess.Popen(["python", "-m", "ocp_vscode"])
|
| 54 |
+
# pre-import build123d and ocp_vscode in main thread
|
| 55 |
+
exec("from build123d import *\nfrom ocp_vscode import *")
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def button_run_callback():
|
| 59 |
+
exec(code.value)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def shutdown_all():
|
| 63 |
+
ocpcv_proc.kill()
|
| 64 |
+
# ocpcv_proc.terminate() # TODO: investigate best cross-platform solution
|
| 65 |
+
app.shutdown()
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
app.on_startup(startup_all)
|
| 69 |
+
|
| 70 |
+
button_frac = 0.05
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
with ui.splitter().classes(
|
| 74 |
+
"w-full h-[calc(100vh-2rem)] no-wrap items-stretch border"
|
| 75 |
+
) as splitter:
|
| 76 |
+
with splitter.before:
|
| 77 |
+
with ui.column().classes("w-full items-stretch border"):
|
| 78 |
+
with ui.row():
|
| 79 |
+
with ui.column().classes("w-1/3"):
|
| 80 |
+
ui.button(
|
| 81 |
+
"Run Code", icon="send", on_click=lambda: button_run_callback()
|
| 82 |
+
).classes(f"h-[calc(100vh*{button_frac}-3rem)]")
|
| 83 |
+
# ui.button('shutdown', on_click=lambda: shutdown_all()) # just close the window
|
| 84 |
+
code = (
|
| 85 |
+
ui.codemirror(
|
| 86 |
+
'print("Edit me!")\nprint("hello world")',
|
| 87 |
+
language="Python",
|
| 88 |
+
theme="vscodeLight",
|
| 89 |
+
)
|
| 90 |
+
.classes(f"h-[calc(100vh*{1-button_frac}-3rem)]")
|
| 91 |
+
.style(f"font-size: {editor_fontsize}px")
|
| 92 |
+
)
|
| 93 |
+
with splitter.after:
|
| 94 |
+
with ui.column().classes("w-full items-stretch border"):
|
| 95 |
+
ocpcv = (
|
| 96 |
+
ui.element("iframe")
|
| 97 |
+
.props('src="http://127.0.0.1:3939/viewer"')
|
| 98 |
+
.classes("h-[calc(100vh-3rem)]")
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
# handle the CTRL + Enter run shortcut:
|
| 103 |
+
def handle_key(e: KeyEventArguments):
|
| 104 |
+
if e.modifiers.ctrl and e.action.keydown:
|
| 105 |
+
if e.key.enter:
|
| 106 |
+
button_run_callback()
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
keyboard = ui.keyboard(on_key=handle_key)
|
| 110 |
+
# TODO: consider separating this module and how best to organize it (if name == main, etc.)
|
| 111 |
+
app.on_shutdown(shutdown_all) # register shutdown handler
|
| 112 |
+
ui.run(
|
| 113 |
+
native=True,
|
| 114 |
+
window_size=(1800, 900),
|
| 115 |
+
title="nicegui-cadviewer",
|
| 116 |
+
fullscreen=False,
|
| 117 |
+
reload=False,
|
| 118 |
+
)
|
| 119 |
+
# ui.run(native=True, window_size=(1800, 900), fullscreen=False, reload=True) #use reload=True when developing rapidly, False helps exit behavior
|
| 120 |
+
|
| 121 |
+
# layout info https://github.com/zauberzeug/nicegui/discussions/1937
|