jadeui 0.1.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jadeui/__init__.py +156 -0
- jadeui/app.py +370 -0
- jadeui/core/__init__.py +33 -0
- jadeui/core/dll.py +361 -0
- jadeui/core/lifecycle.py +76 -0
- jadeui/core/types.py +168 -0
- jadeui/dll/JadeView-dist_x64/JadeView.dll_x64.exp +0 -0
- jadeui/dll/JadeView-dist_x64/JadeView.dll_x64.lib +0 -0
- jadeui/dll/JadeView-dist_x64/JadeView_x64.dll +0 -0
- jadeui/dll/JadeView-dist_x64/JadeView_x64.pdb +0 -0
- jadeui/downloader.py +346 -0
- jadeui/events.py +281 -0
- jadeui/exceptions.py +41 -0
- jadeui/ipc.py +171 -0
- jadeui/router.py +534 -0
- jadeui/server.py +141 -0
- jadeui/templates/__init__.py +20 -0
- jadeui/templates/default.css +390 -0
- jadeui/utils.py +69 -0
- jadeui/window.py +762 -0
- jadeui-0.1.0.dist-info/METADATA +247 -0
- jadeui-0.1.0.dist-info/RECORD +24 -0
- jadeui-0.1.0.dist-info/WHEEL +4 -0
- jadeui-0.1.0.dist-info/entry_points.txt +2 -0
jadeui/__init__.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JadeUI Python SDK - Desktop Application Framework
|
|
3
|
+
|
|
4
|
+
A Python SDK for creating desktop applications using JadeView's WebView technology.
|
|
5
|
+
Provides a clean, object-oriented API for window management, IPC communication,
|
|
6
|
+
and web frontend integration.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
from jadeui import JadeUIApp, Window
|
|
10
|
+
|
|
11
|
+
app = JadeUIApp()
|
|
12
|
+
|
|
13
|
+
@app.on_ready
|
|
14
|
+
def on_ready():
|
|
15
|
+
window = Window(
|
|
16
|
+
title="My App",
|
|
17
|
+
width=1024,
|
|
18
|
+
height=768,
|
|
19
|
+
url="https://example.com"
|
|
20
|
+
)
|
|
21
|
+
window.show()
|
|
22
|
+
|
|
23
|
+
app.run()
|
|
24
|
+
|
|
25
|
+
Example with local server:
|
|
26
|
+
from jadeui import JadeUIApp, Window, LocalServer
|
|
27
|
+
|
|
28
|
+
app = JadeUIApp()
|
|
29
|
+
server = LocalServer()
|
|
30
|
+
|
|
31
|
+
@app.on_ready
|
|
32
|
+
def on_ready():
|
|
33
|
+
url = server.start("./web", "myapp")
|
|
34
|
+
window = Window(title="My App", url=f"{url}/index.html")
|
|
35
|
+
window.show()
|
|
36
|
+
|
|
37
|
+
app.run()
|
|
38
|
+
|
|
39
|
+
Example with IPC:
|
|
40
|
+
from jadeui import JadeUIApp, Window, IPCManager
|
|
41
|
+
|
|
42
|
+
app = JadeUIApp()
|
|
43
|
+
ipc = IPCManager()
|
|
44
|
+
|
|
45
|
+
@ipc.on("message")
|
|
46
|
+
def handle_message(window_id, message):
|
|
47
|
+
print(f"Received: {message}")
|
|
48
|
+
ipc.send(window_id, "message", f"Echo: {message}")
|
|
49
|
+
return 1
|
|
50
|
+
|
|
51
|
+
@app.on_ready
|
|
52
|
+
def on_ready():
|
|
53
|
+
window = Window(title="IPC Demo", url="...")
|
|
54
|
+
window.show()
|
|
55
|
+
|
|
56
|
+
app.run()
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
from .app import JadeUIApp
|
|
60
|
+
from .window import Window, Theme, Backdrop
|
|
61
|
+
from .ipc import IPCManager
|
|
62
|
+
from .server import LocalServer
|
|
63
|
+
from .events import EventEmitter, Events
|
|
64
|
+
from .router import Router
|
|
65
|
+
from .core.types import RGBA, WebViewWindowOptions, WebViewSettings
|
|
66
|
+
from .exceptions import (
|
|
67
|
+
JadeUIError,
|
|
68
|
+
DLLLoadError,
|
|
69
|
+
WindowCreationError,
|
|
70
|
+
IPCError,
|
|
71
|
+
ServerError,
|
|
72
|
+
InitializationError,
|
|
73
|
+
)
|
|
74
|
+
from .downloader import (
|
|
75
|
+
download_dll,
|
|
76
|
+
ensure_dll,
|
|
77
|
+
find_dll,
|
|
78
|
+
get_architecture,
|
|
79
|
+
VERSION as DLL_VERSION,
|
|
80
|
+
)
|
|
81
|
+
from . import utils
|
|
82
|
+
|
|
83
|
+
__version__ = "0.1.0"
|
|
84
|
+
__author__ = "JadeView Team"
|
|
85
|
+
__license__ = "MIT"
|
|
86
|
+
|
|
87
|
+
__all__ = [
|
|
88
|
+
# Main classes
|
|
89
|
+
"JadeUIApp",
|
|
90
|
+
"Window",
|
|
91
|
+
"IPCManager",
|
|
92
|
+
"LocalServer",
|
|
93
|
+
"Router",
|
|
94
|
+
# Constants
|
|
95
|
+
"Theme",
|
|
96
|
+
"Backdrop",
|
|
97
|
+
"Events",
|
|
98
|
+
# Types
|
|
99
|
+
"RGBA",
|
|
100
|
+
"WebViewWindowOptions",
|
|
101
|
+
"WebViewSettings",
|
|
102
|
+
# Events
|
|
103
|
+
"EventEmitter",
|
|
104
|
+
# Exceptions
|
|
105
|
+
"JadeUIError",
|
|
106
|
+
"DLLLoadError",
|
|
107
|
+
"WindowCreationError",
|
|
108
|
+
"IPCError",
|
|
109
|
+
"ServerError",
|
|
110
|
+
"InitializationError",
|
|
111
|
+
# DLL Downloader
|
|
112
|
+
"download_dll",
|
|
113
|
+
"ensure_dll",
|
|
114
|
+
"find_dll",
|
|
115
|
+
"get_architecture",
|
|
116
|
+
"DLL_VERSION",
|
|
117
|
+
# Utilities
|
|
118
|
+
"utils",
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def create_app(
|
|
123
|
+
enable_dev_tools: bool = False,
|
|
124
|
+
user_data_dir: str = None,
|
|
125
|
+
log_file: str = None,
|
|
126
|
+
) -> JadeUIApp:
|
|
127
|
+
"""Create and initialize a JadeUI application
|
|
128
|
+
|
|
129
|
+
Convenience function for quick app creation.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
enable_dev_tools: Whether to enable developer tools
|
|
133
|
+
user_data_dir: Directory for user data storage
|
|
134
|
+
log_file: Path to log file
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Initialized JadeUIApp instance
|
|
138
|
+
|
|
139
|
+
Example:
|
|
140
|
+
from jadeui import create_app, Window
|
|
141
|
+
|
|
142
|
+
app = create_app()
|
|
143
|
+
|
|
144
|
+
@app.on_ready
|
|
145
|
+
def setup():
|
|
146
|
+
Window(title="My App", url="https://example.com").show()
|
|
147
|
+
|
|
148
|
+
app.run()
|
|
149
|
+
"""
|
|
150
|
+
app = JadeUIApp()
|
|
151
|
+
app.initialize(
|
|
152
|
+
enable_dev_tools=enable_dev_tools,
|
|
153
|
+
user_data_dir=user_data_dir,
|
|
154
|
+
log_file=log_file,
|
|
155
|
+
)
|
|
156
|
+
return app
|
jadeui/app.py
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JadeUI Application
|
|
3
|
+
|
|
4
|
+
Main application class for JadeUI desktop applications.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import ctypes
|
|
8
|
+
import logging
|
|
9
|
+
import signal
|
|
10
|
+
import sys
|
|
11
|
+
import threading
|
|
12
|
+
from typing import Optional, Callable, Any
|
|
13
|
+
|
|
14
|
+
from .core import DLLManager, LifecycleManager
|
|
15
|
+
from .events import EventEmitter, GlobalEventManager, Events
|
|
16
|
+
from .exceptions import InitializationError
|
|
17
|
+
from .core.types import (
|
|
18
|
+
AppReadyCallback,
|
|
19
|
+
WindowAllClosedCallback,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class JadeUIApp(EventEmitter):
|
|
26
|
+
"""Main JadeUI application class
|
|
27
|
+
|
|
28
|
+
This is the central class for JadeUI applications. It manages the application
|
|
29
|
+
lifecycle, DLL loading, and global event handling.
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
app = JadeUIApp()
|
|
33
|
+
|
|
34
|
+
@app.on('ready')
|
|
35
|
+
def on_ready():
|
|
36
|
+
# Create windows here
|
|
37
|
+
window = Window("My App")
|
|
38
|
+
window.show()
|
|
39
|
+
|
|
40
|
+
app.run()
|
|
41
|
+
|
|
42
|
+
Events:
|
|
43
|
+
- 'ready': Fired when app is initialized and ready
|
|
44
|
+
- 'error': Fired when an error occurs
|
|
45
|
+
- 'window-all-closed': Fired when all windows are closed
|
|
46
|
+
- 'before-quit': Fired before app quits
|
|
47
|
+
|
|
48
|
+
Attributes:
|
|
49
|
+
dll_manager: The DLL manager instance
|
|
50
|
+
lifecycle_manager: The lifecycle manager instance
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
_instance: Optional["JadeUIApp"] = None
|
|
54
|
+
|
|
55
|
+
def __new__(cls) -> "JadeUIApp":
|
|
56
|
+
if cls._instance is None:
|
|
57
|
+
cls._instance = super().__new__(cls)
|
|
58
|
+
return cls._instance
|
|
59
|
+
|
|
60
|
+
def __init__(self):
|
|
61
|
+
if hasattr(self, "_initialized") and self._initialized:
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
super().__init__()
|
|
65
|
+
self._initialized = False
|
|
66
|
+
self.dll_manager = DLLManager()
|
|
67
|
+
self.lifecycle_manager = LifecycleManager()
|
|
68
|
+
self._dev_tools_enabled = False
|
|
69
|
+
self._log_file: Optional[str] = None
|
|
70
|
+
self._data_directory: Optional[str] = None
|
|
71
|
+
|
|
72
|
+
# Callback references to prevent garbage collection
|
|
73
|
+
self._callbacks: list = []
|
|
74
|
+
|
|
75
|
+
# Global event manager
|
|
76
|
+
self._global_events: Optional[GlobalEventManager] = None
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def get_instance(cls) -> Optional["JadeUIApp"]:
|
|
80
|
+
"""Get the singleton instance of the app
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
The app instance or None if not created
|
|
84
|
+
"""
|
|
85
|
+
return cls._instance
|
|
86
|
+
|
|
87
|
+
def initialize(
|
|
88
|
+
self,
|
|
89
|
+
enable_dev_tools: bool = False,
|
|
90
|
+
log_file: Optional[str] = None,
|
|
91
|
+
data_directory: Optional[str] = None,
|
|
92
|
+
) -> "JadeUIApp":
|
|
93
|
+
"""Initialize the JadeUI application
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
enable_dev_tools: Whether to enable developer tools (F12)
|
|
97
|
+
log_file: Path to log file (None disables file logging)
|
|
98
|
+
data_directory: WebView data directory (None uses default, current directory)
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Self for chaining
|
|
102
|
+
|
|
103
|
+
Raises:
|
|
104
|
+
InitializationError: If initialization fails
|
|
105
|
+
"""
|
|
106
|
+
if self._initialized:
|
|
107
|
+
return self
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
# Store configuration
|
|
111
|
+
self._dev_tools_enabled = enable_dev_tools
|
|
112
|
+
self._log_file = log_file
|
|
113
|
+
self._data_directory = data_directory
|
|
114
|
+
|
|
115
|
+
# Initialize lifecycle manager
|
|
116
|
+
self.lifecycle_manager.initialize()
|
|
117
|
+
self.lifecycle_manager.add_cleanup_callback(self._cleanup)
|
|
118
|
+
|
|
119
|
+
# Load DLL
|
|
120
|
+
self.dll_manager.load()
|
|
121
|
+
|
|
122
|
+
# Initialize JadeView DLL
|
|
123
|
+
# API: JadeView_init(enable_devtools, log_path, data_directory)
|
|
124
|
+
result = self.dll_manager.JadeView_init(
|
|
125
|
+
1 if enable_dev_tools else 0,
|
|
126
|
+
log_file.encode("utf-8") if log_file else None,
|
|
127
|
+
data_directory.encode("utf-8") if data_directory else None,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if result == 0:
|
|
131
|
+
raise InitializationError("JadeView DLL initialization failed")
|
|
132
|
+
|
|
133
|
+
# Create global event manager
|
|
134
|
+
self._global_events = GlobalEventManager(self.dll_manager)
|
|
135
|
+
|
|
136
|
+
# Register global event handlers
|
|
137
|
+
self._register_global_events()
|
|
138
|
+
|
|
139
|
+
self._initialized = True
|
|
140
|
+
logger.info("JadeUI application initialized successfully")
|
|
141
|
+
return self
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
raise InitializationError(f"Failed to initialize JadeUI: {e}")
|
|
145
|
+
|
|
146
|
+
def _register_global_events(self) -> None:
|
|
147
|
+
"""Register global event handlers with the DLL"""
|
|
148
|
+
# Create app-ready callback
|
|
149
|
+
@AppReadyCallback
|
|
150
|
+
def app_ready_callback(success: int, reason: ctypes.c_char_p) -> int:
|
|
151
|
+
reason_str = reason.decode("utf-8") if reason else "unknown"
|
|
152
|
+
return self._on_app_ready(success, reason_str)
|
|
153
|
+
|
|
154
|
+
# Create window-all-closed callback
|
|
155
|
+
@WindowAllClosedCallback
|
|
156
|
+
def window_all_closed_callback() -> int:
|
|
157
|
+
return self._on_window_all_closed()
|
|
158
|
+
|
|
159
|
+
# Store references to prevent garbage collection
|
|
160
|
+
self._callbacks.append(app_ready_callback)
|
|
161
|
+
self._callbacks.append(window_all_closed_callback)
|
|
162
|
+
|
|
163
|
+
# Register with DLL
|
|
164
|
+
self.dll_manager.jade_on(
|
|
165
|
+
b"app-ready",
|
|
166
|
+
ctypes.cast(app_ready_callback, ctypes.c_void_p),
|
|
167
|
+
)
|
|
168
|
+
self.dll_manager.jade_on(
|
|
169
|
+
b"window-all-closed",
|
|
170
|
+
ctypes.cast(window_all_closed_callback, ctypes.c_void_p),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
logger.info("Global event handlers registered")
|
|
174
|
+
|
|
175
|
+
def _on_app_ready(self, success: int, reason: str) -> int:
|
|
176
|
+
"""Handle app-ready event"""
|
|
177
|
+
try:
|
|
178
|
+
if success == 1 and reason == "success":
|
|
179
|
+
logger.info("JadeUI app ready")
|
|
180
|
+
self.emit("ready")
|
|
181
|
+
else:
|
|
182
|
+
logger.error(f"JadeUI app failed to initialize: {reason}")
|
|
183
|
+
self.emit(
|
|
184
|
+
"error",
|
|
185
|
+
InitializationError(f"App initialization failed: {reason}"),
|
|
186
|
+
)
|
|
187
|
+
except Exception as e:
|
|
188
|
+
logger.error(f"Error in app-ready handler: {e}")
|
|
189
|
+
return 0
|
|
190
|
+
|
|
191
|
+
def _on_window_all_closed(self) -> int:
|
|
192
|
+
"""Handle window-all-closed event"""
|
|
193
|
+
logger.info("All windows closed")
|
|
194
|
+
self.emit("window-all-closed")
|
|
195
|
+
# Default behavior: cleanup when all windows are closed
|
|
196
|
+
self._cleanup()
|
|
197
|
+
return 0
|
|
198
|
+
|
|
199
|
+
def run(self) -> None:
|
|
200
|
+
"""Start the application message loop
|
|
201
|
+
|
|
202
|
+
This method blocks until all windows are closed.
|
|
203
|
+
Call this after setting up event handlers and windows.
|
|
204
|
+
|
|
205
|
+
Supports Ctrl+C to terminate the application.
|
|
206
|
+
"""
|
|
207
|
+
if not self._initialized:
|
|
208
|
+
self.initialize()
|
|
209
|
+
|
|
210
|
+
# 设置信号处理器
|
|
211
|
+
self._setup_signal_handlers()
|
|
212
|
+
|
|
213
|
+
logger.info("Starting JadeUI message loop")
|
|
214
|
+
try:
|
|
215
|
+
self.dll_manager.run_message_loop()
|
|
216
|
+
except KeyboardInterrupt:
|
|
217
|
+
logger.info("Application interrupted by user (Ctrl+C)")
|
|
218
|
+
finally:
|
|
219
|
+
self._cleanup()
|
|
220
|
+
|
|
221
|
+
def _setup_signal_handlers(self) -> None:
|
|
222
|
+
"""设置信号处理器以支持 Ctrl+C"""
|
|
223
|
+
self._shutting_down = False
|
|
224
|
+
|
|
225
|
+
def signal_handler(signum, frame):
|
|
226
|
+
if self._shutting_down:
|
|
227
|
+
return
|
|
228
|
+
self._shutting_down = True
|
|
229
|
+
logger.info(f"Received signal {signum}, shutting down...")
|
|
230
|
+
self._force_quit()
|
|
231
|
+
|
|
232
|
+
# 注册 SIGINT (Ctrl+C) 和 SIGTERM
|
|
233
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
234
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
235
|
+
|
|
236
|
+
# Windows: 设置控制台控制处理器
|
|
237
|
+
if sys.platform == "win32":
|
|
238
|
+
self._setup_windows_console_handler()
|
|
239
|
+
|
|
240
|
+
def _setup_windows_console_handler(self) -> None:
|
|
241
|
+
"""设置 Windows 控制台控制处理器"""
|
|
242
|
+
try:
|
|
243
|
+
# 使用 ctypes 直接调用 Windows API
|
|
244
|
+
kernel32 = ctypes.windll.kernel32
|
|
245
|
+
|
|
246
|
+
# BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
|
|
247
|
+
HANDLER_ROUTINE = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_ulong)
|
|
248
|
+
|
|
249
|
+
CTRL_C_EVENT = 0
|
|
250
|
+
CTRL_BREAK_EVENT = 1
|
|
251
|
+
CTRL_CLOSE_EVENT = 2
|
|
252
|
+
|
|
253
|
+
@HANDLER_ROUTINE
|
|
254
|
+
def console_handler(ctrl_type):
|
|
255
|
+
if ctrl_type in (CTRL_C_EVENT, CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT):
|
|
256
|
+
if not self._shutting_down:
|
|
257
|
+
self._shutting_down = True
|
|
258
|
+
logger.info("Console control event received, shutting down...")
|
|
259
|
+
# 在新线程中执行清理,避免阻塞
|
|
260
|
+
threading.Thread(target=self._force_quit, daemon=True).start()
|
|
261
|
+
return True
|
|
262
|
+
return False
|
|
263
|
+
|
|
264
|
+
# 保存引用防止垃圾回收
|
|
265
|
+
self._console_handler = console_handler
|
|
266
|
+
kernel32.SetConsoleCtrlHandler(console_handler, True)
|
|
267
|
+
logger.debug("Windows console handler registered")
|
|
268
|
+
except Exception as e:
|
|
269
|
+
logger.warning(f"Could not set Windows console handler: {e}")
|
|
270
|
+
|
|
271
|
+
def _force_quit(self) -> None:
|
|
272
|
+
"""强制退出应用"""
|
|
273
|
+
try:
|
|
274
|
+
# 清理窗口
|
|
275
|
+
self.dll_manager.cleanup_all_windows()
|
|
276
|
+
|
|
277
|
+
# Windows: 发送退出消息到消息循环
|
|
278
|
+
if sys.platform == "win32":
|
|
279
|
+
try:
|
|
280
|
+
user32 = ctypes.windll.user32
|
|
281
|
+
# PostQuitMessage 会导致 GetMessage 返回 0,从而退出消息循环
|
|
282
|
+
user32.PostQuitMessage(0)
|
|
283
|
+
except Exception as e:
|
|
284
|
+
logger.warning(f"PostQuitMessage failed: {e}")
|
|
285
|
+
|
|
286
|
+
except Exception as e:
|
|
287
|
+
logger.error(f"Error during force quit: {e}")
|
|
288
|
+
finally:
|
|
289
|
+
# 确保进程退出
|
|
290
|
+
import os
|
|
291
|
+
os._exit(0)
|
|
292
|
+
|
|
293
|
+
def quit(self) -> None:
|
|
294
|
+
"""Quit the application
|
|
295
|
+
|
|
296
|
+
Cleans up all resources and exits the message loop.
|
|
297
|
+
"""
|
|
298
|
+
logger.info("Quitting JadeUI application")
|
|
299
|
+
self.emit("before-quit")
|
|
300
|
+
self._cleanup()
|
|
301
|
+
|
|
302
|
+
def _cleanup(self) -> None:
|
|
303
|
+
"""Clean up application resources"""
|
|
304
|
+
if not self._initialized:
|
|
305
|
+
return
|
|
306
|
+
|
|
307
|
+
try:
|
|
308
|
+
self.dll_manager.cleanup_all_windows()
|
|
309
|
+
logger.info("Application resources cleaned up")
|
|
310
|
+
except Exception as e:
|
|
311
|
+
logger.error(f"Error during cleanup: {e}")
|
|
312
|
+
|
|
313
|
+
def is_ready(self) -> bool:
|
|
314
|
+
"""Check if the application is initialized and ready
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
True if app is ready
|
|
318
|
+
"""
|
|
319
|
+
return self._initialized
|
|
320
|
+
|
|
321
|
+
@property
|
|
322
|
+
def dev_tools_enabled(self) -> bool:
|
|
323
|
+
"""Check if developer tools are enabled"""
|
|
324
|
+
return self._dev_tools_enabled
|
|
325
|
+
|
|
326
|
+
def on_ready(self, callback: Callable[[], Any]) -> Callable[[], Any]:
|
|
327
|
+
"""Decorator for ready event
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
callback: Function to call when app is ready
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
The callback function
|
|
334
|
+
|
|
335
|
+
Example:
|
|
336
|
+
@app.on_ready
|
|
337
|
+
def setup():
|
|
338
|
+
window = Window("My App")
|
|
339
|
+
window.show()
|
|
340
|
+
"""
|
|
341
|
+
self.on("ready", callback)
|
|
342
|
+
return callback
|
|
343
|
+
|
|
344
|
+
def on_window_all_closed(
|
|
345
|
+
self, callback: Callable[[], Any]
|
|
346
|
+
) -> Callable[[], Any]:
|
|
347
|
+
"""Decorator for window-all-closed event
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
callback: Function to call when all windows are closed
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
The callback function
|
|
354
|
+
"""
|
|
355
|
+
self.on("window-all-closed", callback)
|
|
356
|
+
return callback
|
|
357
|
+
|
|
358
|
+
def __enter__(self) -> "JadeUIApp":
|
|
359
|
+
"""Context manager entry"""
|
|
360
|
+
if not self._initialized:
|
|
361
|
+
self.initialize()
|
|
362
|
+
return self
|
|
363
|
+
|
|
364
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
365
|
+
"""Context manager exit"""
|
|
366
|
+
self._cleanup()
|
|
367
|
+
|
|
368
|
+
def __repr__(self) -> str:
|
|
369
|
+
status = "ready" if self._initialized else "not initialized"
|
|
370
|
+
return f"JadeUIApp(status={status}, dev_tools={self._dev_tools_enabled})"
|
jadeui/core/__init__.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JadeUI Core Module
|
|
3
|
+
|
|
4
|
+
Low-level interfaces to the JadeView DLL and type definitions.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .dll import DLLManager
|
|
8
|
+
from .types import (
|
|
9
|
+
RGBA,
|
|
10
|
+
WebViewWindowOptions,
|
|
11
|
+
WebViewSettings,
|
|
12
|
+
WindowEventCallback,
|
|
13
|
+
PageLoadCallback,
|
|
14
|
+
FileDropCallback,
|
|
15
|
+
AppReadyCallback,
|
|
16
|
+
IpcCallback,
|
|
17
|
+
WindowAllClosedCallback,
|
|
18
|
+
)
|
|
19
|
+
from .lifecycle import LifecycleManager
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"DLLManager",
|
|
23
|
+
"RGBA",
|
|
24
|
+
"WebViewWindowOptions",
|
|
25
|
+
"WebViewSettings",
|
|
26
|
+
"LifecycleManager",
|
|
27
|
+
"WindowEventCallback",
|
|
28
|
+
"PageLoadCallback",
|
|
29
|
+
"FileDropCallback",
|
|
30
|
+
"AppReadyCallback",
|
|
31
|
+
"IpcCallback",
|
|
32
|
+
"WindowAllClosedCallback",
|
|
33
|
+
]
|