nova-trame 0.26.2__py3-none-any.whl → 1.0.0rc2__py3-none-any.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.
- nova/trame/view/components/ornl/neutron_data_selector.py +2 -6
- nova/trame/view/components/visualization/matplotlib_figure.py +63 -9
- nova/trame/view/layouts/grid.py +6 -0
- nova/trame/view/layouts/hbox.py +6 -0
- nova/trame/view/layouts/vbox.py +6 -0
- nova/trame/view/theme/assets/core_style.scss +10 -0
- nova/trame/view/theme/theme.py +6 -4
- {nova_trame-0.26.2.dist-info → nova_trame-1.0.0rc2.dist-info}/METADATA +5 -4
- {nova_trame-0.26.2.dist-info → nova_trame-1.0.0rc2.dist-info}/RECORD +12 -12
- {nova_trame-0.26.2.dist-info → nova_trame-1.0.0rc2.dist-info}/WHEEL +1 -1
- {nova_trame-0.26.2.dist-info → nova_trame-1.0.0rc2.dist-info}/entry_points.txt +0 -0
- {nova_trame-0.26.2.dist-info → nova_trame-1.0.0rc2.dist-info/licenses}/LICENSE +0 -0
@@ -292,6 +292,8 @@ class NeutronDataSelector(DataSelector):
|
|
292
292
|
projection=set_state_param(self.state, self._projection, projection)
|
293
293
|
)
|
294
294
|
|
295
|
+
super()._setup_bindings()
|
296
|
+
|
295
297
|
# These update methods notify the rest of the application when the component changes bound parameters.
|
296
298
|
def update_facility(self, facility: str) -> None:
|
297
299
|
self._vm.set_binding_parameters(
|
@@ -317,9 +319,3 @@ class NeutronDataSelector(DataSelector):
|
|
317
319
|
experiment=set_state_param(self.state, (self._selected_experiment_name,), experiment),
|
318
320
|
)
|
319
321
|
self._vm.reset()
|
320
|
-
|
321
|
-
def set_state(self, *args: Any, **kwargs: Any) -> None:
|
322
|
-
raise TypeError(
|
323
|
-
"The set_state method has been removed. Please use update_facility, update_instrument, and "
|
324
|
-
"update_experiment instead."
|
325
|
-
)
|
@@ -9,6 +9,7 @@ from mimetypes import types_map
|
|
9
9
|
from pathlib import Path
|
10
10
|
from threading import Thread
|
11
11
|
from typing import Any, Optional
|
12
|
+
from warnings import warn
|
12
13
|
|
13
14
|
import tornado
|
14
15
|
from aiohttp import ClientSession, WSMsgType, web
|
@@ -214,17 +215,23 @@ class MatplotlibFigure(matplotlib.Figure):
|
|
214
215
|
-------
|
215
216
|
None
|
216
217
|
""" # noqa: E501
|
218
|
+
self._server = get_server(None, client_type="vue3")
|
217
219
|
self._webagg = webagg
|
220
|
+
if "classes" in kwargs:
|
221
|
+
kwargs["classes"] += " h-100 w-100 overflow-hidden"
|
222
|
+
else:
|
223
|
+
kwargs["classes"] = "h-100 w-100 overflow-hidden"
|
218
224
|
if webagg:
|
219
|
-
self.
|
220
|
-
if "
|
221
|
-
kwargs
|
222
|
-
|
223
|
-
kwargs["classes"] = "nova-mpl"
|
225
|
+
self._initial_resize = True
|
226
|
+
if "id" in kwargs:
|
227
|
+
kwargs.pop("id")
|
228
|
+
warn("id parameter to MatplotlibFigure is ignored when webagg=True.", stacklevel=1)
|
224
229
|
|
225
|
-
|
230
|
+
self._port = MatplotlibFigure._get_free_port()
|
231
|
+
self._id = f"nova_mpl_{self._port}"
|
232
|
+
kwargs["classes"] += " nova-mpl"
|
226
233
|
|
227
|
-
self.
|
234
|
+
html.Div(id=self._id, **kwargs)
|
228
235
|
|
229
236
|
self._figure = figure
|
230
237
|
self._initialized = False
|
@@ -236,8 +243,52 @@ class MatplotlibFigure(matplotlib.Figure):
|
|
236
243
|
self.update()
|
237
244
|
else:
|
238
245
|
super().__init__(figure, **kwargs)
|
246
|
+
self._id = self._key
|
247
|
+
|
248
|
+
self._query_selector = f"window.document.querySelector('#{self._id}')"
|
249
|
+
self._trigger = (
|
250
|
+
"window.trame.trigger("
|
251
|
+
f" '{self._id}_resize',"
|
252
|
+
f" [{self._query_selector}.offsetHeight, {self._query_selector}.offsetWidth, window.devicePixelRatio]"
|
253
|
+
");"
|
254
|
+
)
|
255
|
+
self._resize_figure = client.JSEval(exec=self._trigger).exec
|
256
|
+
self._resize_listener = client.JSEval(
|
257
|
+
exec=(
|
258
|
+
"window.addEventListener('resize', function() {"
|
259
|
+
f" window.delay_manager.debounce('{self._id}', function() {{ {self._trigger} }}, 500);"
|
260
|
+
"});"
|
261
|
+
)
|
262
|
+
).exec
|
263
|
+
|
264
|
+
@self._server.controller.trigger(f"{self._id}_resize")
|
265
|
+
def resize_figure(height: int, width: int, device_pixel_ratio: float) -> None:
|
266
|
+
if self._figure:
|
267
|
+
# This is the browser standard assumption for DPI.
|
268
|
+
dpi = 96
|
269
|
+
|
270
|
+
if self._webagg:
|
271
|
+
# Reserve space for the controls injected by webagg.
|
272
|
+
height -= 48
|
273
|
+
width -= 4
|
239
274
|
|
240
|
-
|
275
|
+
if not self._initial_resize:
|
276
|
+
# Handle device pixel ratio for retina displays
|
277
|
+
dpi = int(dpi * device_pixel_ratio)
|
278
|
+
height = int(height * device_pixel_ratio)
|
279
|
+
width = int(width * device_pixel_ratio)
|
280
|
+
|
281
|
+
self._initial_resize = False
|
282
|
+
|
283
|
+
self._figure.set_dpi(dpi)
|
284
|
+
self._figure.set_size_inches(width / dpi, height / dpi)
|
285
|
+
|
286
|
+
self.update(skip_resize=True)
|
287
|
+
|
288
|
+
client.ClientTriggers(mounted=self._resize_listener)
|
289
|
+
client.ClientTriggers(mounted=self._resize_figure)
|
290
|
+
|
291
|
+
def update(self, figure: Optional[Figure] = None, skip_resize: bool = False) -> None:
|
241
292
|
if self._webagg:
|
242
293
|
if figure:
|
243
294
|
self._figure = figure
|
@@ -255,7 +306,10 @@ class MatplotlibFigure(matplotlib.Figure):
|
|
255
306
|
else:
|
256
307
|
super().update(figure)
|
257
308
|
|
258
|
-
self
|
309
|
+
if not skip_resize and hasattr(self, "_resize_figure"):
|
310
|
+
self._resize_figure()
|
311
|
+
else:
|
312
|
+
self._server.state.flush()
|
259
313
|
|
260
314
|
def _setup_figure_websocket(self) -> None:
|
261
315
|
thread = Thread(target=self._mpl_run_ws_server, daemon=True)
|
nova/trame/view/layouts/grid.py
CHANGED
@@ -19,6 +19,7 @@ class GridLayout(html.Div):
|
|
19
19
|
halign: Optional[str] = None,
|
20
20
|
valign: Optional[str] = None,
|
21
21
|
gap: Optional[Union[int, str]] = "0em",
|
22
|
+
stretch: bool = False,
|
22
23
|
**kwargs: Any,
|
23
24
|
) -> None:
|
24
25
|
"""Constructor for GridLayout.
|
@@ -42,6 +43,9 @@ class GridLayout(html.Div):
|
|
42
43
|
gap : optional[str]
|
43
44
|
The gap to place between items (works both horizontally and vertically). Can be any CSS gap value (e.g.
|
44
45
|
"4px" or "0.25em"). Defaults to no gap between items.
|
46
|
+
stretch : optional[bool]
|
47
|
+
If True, then this layout component will stretch to attempt to fill the space of it's parent container.
|
48
|
+
Defaults to False.
|
45
49
|
kwargs : Any
|
46
50
|
Additional keyword arguments to pass to html.Div.
|
47
51
|
|
@@ -69,6 +73,8 @@ class GridLayout(html.Div):
|
|
69
73
|
if isinstance(classes, list):
|
70
74
|
classes = " ".join(classes)
|
71
75
|
classes += " d-grid"
|
76
|
+
if stretch:
|
77
|
+
classes += " flex-1-1 overflow-y-auto"
|
72
78
|
|
73
79
|
widget_style = self.get_root_styles(columns, height, width, halign, valign, gap)
|
74
80
|
user_style = kwargs.pop("style", {})
|
nova/trame/view/layouts/hbox.py
CHANGED
@@ -18,6 +18,7 @@ class HBoxLayout(html.Div):
|
|
18
18
|
valign: Optional[str] = None,
|
19
19
|
gap: Optional[Union[int, str]] = "0em",
|
20
20
|
vspace: Optional[Union[int, str]] = "0em",
|
21
|
+
stretch: bool = False,
|
21
22
|
**kwargs: Any,
|
22
23
|
) -> None:
|
23
24
|
"""Constructor for HBoxLayout.
|
@@ -42,6 +43,9 @@ class HBoxLayout(html.Div):
|
|
42
43
|
vspace : optional[str]
|
43
44
|
The vertical gap to place between items. Can be any CSS gap value (e.g. "4px" or "0.25em"). Defaults to no
|
44
45
|
gap between items.
|
46
|
+
stretch : optional[bool]
|
47
|
+
If True, then this layout component will stretch to attempt to fill the space of it's parent container.
|
48
|
+
Defaults to False.
|
45
49
|
kwargs : Any
|
46
50
|
Additional keyword arguments to pass to html.Div.
|
47
51
|
|
@@ -60,6 +64,8 @@ class HBoxLayout(html.Div):
|
|
60
64
|
if isinstance(classes, list):
|
61
65
|
classes = " ".join(classes)
|
62
66
|
classes += " d-flex flex-row"
|
67
|
+
if stretch:
|
68
|
+
classes += " flex-1-1 overflow-y-auto"
|
63
69
|
|
64
70
|
widget_style = self.get_root_styles(height, width, halign, valign, gap, vspace)
|
65
71
|
user_style = kwargs.pop("style", {})
|
nova/trame/view/layouts/vbox.py
CHANGED
@@ -18,6 +18,7 @@ class VBoxLayout(html.Div):
|
|
18
18
|
valign: Optional[str] = None,
|
19
19
|
gap: Optional[Union[int, str]] = "0em",
|
20
20
|
vspace: Optional[Union[int, str]] = "0em",
|
21
|
+
stretch: bool = False,
|
21
22
|
**kwargs: Any,
|
22
23
|
) -> None:
|
23
24
|
"""Constructor for VBoxLayout.
|
@@ -42,6 +43,9 @@ class VBoxLayout(html.Div):
|
|
42
43
|
vspace : optional[str]
|
43
44
|
The vertical gap to place between items. Can be any CSS gap value (e.g. "4px" or "0.25em"). Defaults to no
|
44
45
|
gap between items.
|
46
|
+
stretch : optional[bool]
|
47
|
+
If True, then this layout component will stretch to attempt to fill the space of it's parent container.
|
48
|
+
Defaults to False.
|
45
49
|
kwargs : Any
|
46
50
|
Additional keyword arguments to pass to html.Div.
|
47
51
|
|
@@ -60,6 +64,8 @@ class VBoxLayout(html.Div):
|
|
60
64
|
if isinstance(classes, list):
|
61
65
|
classes = " ".join(classes)
|
62
66
|
classes += " d-flex flex-column"
|
67
|
+
if stretch:
|
68
|
+
classes += " flex-1-1 overflow-y-auto"
|
63
69
|
|
64
70
|
widget_style = self.get_root_styles(height, width, halign, valign, gap, vspace)
|
65
71
|
user_style = kwargs.pop("style", {})
|
@@ -70,8 +70,18 @@ html {
|
|
70
70
|
}
|
71
71
|
|
72
72
|
.v-window {
|
73
|
+
display: flex;
|
74
|
+
flex: 1 1;
|
73
75
|
overflow-x: visible !important;
|
74
76
|
overflow-y: visible !important;
|
77
|
+
|
78
|
+
.v-window__container {
|
79
|
+
flex: 1 1;
|
80
|
+
|
81
|
+
.v-window-item {
|
82
|
+
flex: 1 1;
|
83
|
+
}
|
84
|
+
}
|
75
85
|
}
|
76
86
|
|
77
87
|
@media only screen and (max-width: 959px) {
|
nova/trame/view/theme/theme.py
CHANGED
@@ -259,11 +259,13 @@ class ThemedApp:
|
|
259
259
|
|
260
260
|
with vuetify.VMain(classes="align-stretch d-flex flex-column h-screen"):
|
261
261
|
# [slot override example]
|
262
|
-
layout.pre_content = vuetify.VSheet(classes="bg-background ")
|
262
|
+
layout.pre_content = vuetify.VSheet(classes="bg-background flex-0-1 my-1 ")
|
263
263
|
# [slot override example complete]
|
264
|
-
with vuetify.VContainer(classes="flex-
|
265
|
-
layout.content =
|
266
|
-
|
264
|
+
with vuetify.VContainer(classes="flex-1-1 overflow-hidden pt-0 pb-2", fluid=True):
|
265
|
+
layout.content = vuetify.VCard(
|
266
|
+
classes="d-flex flex-column flex-1-1 h-100 my-1 overflow-y-auto pa-1 "
|
267
|
+
)
|
268
|
+
layout.post_content = vuetify.VSheet(classes="bg-background flex-0-1 my-1 ")
|
267
269
|
|
268
270
|
with vuetify.VFooter(
|
269
271
|
app=True,
|
@@ -1,18 +1,19 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: nova-trame
|
3
|
-
Version: 0.
|
3
|
+
Version: 1.0.0rc2
|
4
4
|
Summary: A Python Package for injecting curated themes and custom components into Trame applications
|
5
|
-
License: MIT
|
5
|
+
License-Expression: MIT
|
6
|
+
License-File: LICENSE
|
6
7
|
Keywords: NDIP,Python,Trame,Vuetify
|
7
8
|
Author: John Duggan
|
8
9
|
Author-email: dugganjw@ornl.gov
|
9
10
|
Requires-Python: >=3.10,<4.0
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
16
17
|
Requires-Dist: altair
|
17
18
|
Requires-Dist: blinker (>=1.9.0,<2.0.0)
|
18
19
|
Requires-Dist: libsass
|
@@ -12,27 +12,27 @@ nova/trame/view/components/execution_buttons.py,sha256=Br6uAmE5bY67TTYc5ZTHECNJ_
|
|
12
12
|
nova/trame/view/components/file_upload.py,sha256=WOaFXeNNwN0DYZJr-W6vWdBiTpr7m-lq3WKJaHmeMe8,4560
|
13
13
|
nova/trame/view/components/input_field.py,sha256=xzCmNEoB4ljGx99-gGgTV0UwriwtS8ce22zPA4QneZw,17372
|
14
14
|
nova/trame/view/components/ornl/__init__.py,sha256=HnxzzSsxw0vQSDCVFfWsAxx1n3HnU37LMuQkfiewmSU,90
|
15
|
-
nova/trame/view/components/ornl/neutron_data_selector.py,sha256=
|
15
|
+
nova/trame/view/components/ornl/neutron_data_selector.py,sha256=duiPbROIYsU6h0oZP27wSce6BJuW1mdT8mGoxY05lyw,16542
|
16
16
|
nova/trame/view/components/progress_bar.py,sha256=zhbJwPy_HPQ8YL-ISN8sCRUQ7qY6qqo9wiV59BmvL8I,3038
|
17
17
|
nova/trame/view/components/remote_file_input.py,sha256=mcz_bmI2rD8gdmIOKLhlzfj-XoWBwC99T9ZgQORaKqE,14674
|
18
18
|
nova/trame/view/components/tool_outputs.py,sha256=IbYV4VjrkWAE354Bh5KH76SPsxGLIkOXChijS4-ce_Y,2408
|
19
19
|
nova/trame/view/components/visualization/__init__.py,sha256=reqkkbhD5uSksHHlhVMy1qNUCwSekS5HlXk6wCREYxU,152
|
20
20
|
nova/trame/view/components/visualization/interactive_2d_plot.py,sha256=z2s1janxAclpMEdDJk3z-CQ6r3KPNoR_SXPx9ppWnuQ,3481
|
21
|
-
nova/trame/view/components/visualization/matplotlib_figure.py,sha256=
|
21
|
+
nova/trame/view/components/visualization/matplotlib_figure.py,sha256=PhLZ95ofl78M2I5JMRdQeJZit9du-rW2H_km0jWF3Rg,14756
|
22
22
|
nova/trame/view/layouts/__init__.py,sha256=cMrlB5YMUoK8EGB83b34UU0kPTVrH8AxsYvKRtpUNEc,141
|
23
|
-
nova/trame/view/layouts/grid.py,sha256=
|
24
|
-
nova/trame/view/layouts/hbox.py,sha256=
|
23
|
+
nova/trame/view/layouts/grid.py,sha256=lQVLnpmOvT2y6-gUEgmdE1VvodLxlul6i5Hov202uOo,5816
|
24
|
+
nova/trame/view/layouts/hbox.py,sha256=RJphvkcdvcke1y_R85BR_DI54zPVRQFiU-S1m7U56LI,3801
|
25
25
|
nova/trame/view/layouts/utils.py,sha256=Hg34VQWTG3yHBsgNvmfatR4J-uL3cko7UxSJpT-h3JI,376
|
26
|
-
nova/trame/view/layouts/vbox.py,sha256=
|
26
|
+
nova/trame/view/layouts/vbox.py,sha256=V7bzDjznUNruHd5RDlbbS8eLKxfJvS9iUHTRW8twSVM,3802
|
27
27
|
nova/trame/view/theme/__init__.py,sha256=70_marDlTigIcPEOGiJb2JTs-8b2sGM5SlY7XBPtBDM,54
|
28
|
-
nova/trame/view/theme/assets/core_style.scss,sha256=
|
28
|
+
nova/trame/view/theme/assets/core_style.scss,sha256=lZK8zghy4ExmNuFI-rfq7qt2S7bqObzM_MBviOlWP5c,4481
|
29
29
|
nova/trame/view/theme/assets/favicon.png,sha256=Xbp1nUmhcBDeObjsebEbEAraPDZ_M163M_ZLtm5AbQc,1927
|
30
30
|
nova/trame/view/theme/assets/js/delay_manager.js,sha256=BN4OL88QsyZG4XQ1sTorHpN1rwD4GnWoVKHvl5F5ydo,776
|
31
31
|
nova/trame/view/theme/assets/js/lodash.min.js,sha256=KCyAYJ-fsqtp_HMwbjhy6IKjlA5lrVrtWt1JdMsC57k,73016
|
32
32
|
nova/trame/view/theme/assets/js/revo_grid.js,sha256=fbuEWO8etw-xgo9tjJGjJXdd5wL8qpgabPmrnU6Jp8k,4081
|
33
33
|
nova/trame/view/theme/assets/vuetify_config.json,sha256=a0FSgpLYWGFlRGSMhMq61MyDFBEBwvz55G4qjkM08cs,5627
|
34
34
|
nova/trame/view/theme/exit_button.py,sha256=Kqv1GVJZGrSsj6_JFjGU3vm3iNuMolLC2T1x2IsdmV0,3094
|
35
|
-
nova/trame/view/theme/theme.py,sha256=
|
35
|
+
nova/trame/view/theme/theme.py,sha256=gdmHWyYgLThv8_UHwstbSpBhHnlvIHdADIepxgqVy9Q,13274
|
36
36
|
nova/trame/view/utilities/local_storage.py,sha256=vD8f2VZIpxhIKjZwEaD7siiPCTZO4cw9AfhwdawwYLY,3218
|
37
37
|
nova/trame/view_model/data_selector.py,sha256=jAtq5hpohQ6YiLBbgLJfNUzWZBpN2bjCG_c_FCJu2ns,3186
|
38
38
|
nova/trame/view_model/execution_buttons.py,sha256=MfKSp95D92EqpD48C15cBo6dLO0Yld4FeRZMJNxJf7Y,3551
|
@@ -40,8 +40,8 @@ nova/trame/view_model/ornl/neutron_data_selector.py,sha256=PIKQyzcHpwu81DNk3d8Af
|
|
40
40
|
nova/trame/view_model/progress_bar.py,sha256=6AUKHF3hfzbdsHqNEnmHRgDcBKY5TT8ywDx9S6ovnsc,2854
|
41
41
|
nova/trame/view_model/remote_file_input.py,sha256=zWOflmCDJYYR_pacHphwzricV667GSRokh-mlxpBAOo,3646
|
42
42
|
nova/trame/view_model/tool_outputs.py,sha256=ev6LY7fJ0H2xAJn9f5ww28c8Kpom2SYc2FbvFcoN4zg,829
|
43
|
-
nova_trame-0.
|
44
|
-
nova_trame-0.
|
45
|
-
nova_trame-0.
|
46
|
-
nova_trame-0.
|
47
|
-
nova_trame-0.
|
43
|
+
nova_trame-1.0.0rc2.dist-info/METADATA,sha256=4pMFtoku0PIb83aIpNWcb_OObxTfWoqW_CTF_BcSUz8,1798
|
44
|
+
nova_trame-1.0.0rc2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
45
|
+
nova_trame-1.0.0rc2.dist-info/entry_points.txt,sha256=J2AmeSwiTYZ4ZqHHp9HO6v4MaYQTTBPbNh6WtoqOT58,42
|
46
|
+
nova_trame-1.0.0rc2.dist-info/licenses/LICENSE,sha256=Iu5QiDbwNbREg75iYaxIJ_V-zppuv4QFuBhAW-qiAlM,1061
|
47
|
+
nova_trame-1.0.0rc2.dist-info/RECORD,,
|
File without changes
|
File without changes
|