scitex 2.10.3__py3-none-any.whl → 2.11.0__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.
- scitex/__init__.py +1 -4
- scitex/__version__.py +1 -1
- scitex/_install_guide.py +14 -2
- scitex/bridge/_figrecipe.py +1 -1
- scitex/bridge/_helpers.py +1 -1
- scitex/bridge/_plt_vis.py +1 -1
- scitex/bridge/_stats_plt.py +1 -1
- scitex/bridge/_stats_vis.py +2 -2
- scitex/{fig → canvas}/__init__.py +84 -96
- scitex/{fig → canvas}/backend/_parser.py +1 -1
- scitex/{fig → canvas}/canvas.py +13 -14
- scitex/{fts/_fig/_editor → canvas/editor}/_defaults.py +2 -2
- scitex/{fig → canvas}/editor/edit/__init__.py +11 -14
- scitex/{fig → canvas}/editor/edit/bundle_resolver.py +56 -48
- scitex/{fig → canvas}/editor/edit/editor_launcher.py +79 -26
- scitex/{fts/_fig/_editor/_cui/_panel_loader.py → canvas/editor/edit/panel_loader.py} +8 -8
- scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_bbox.py +2 -1
- scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_core.py +84 -84
- scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_renderer.py +7 -6
- scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/static/css/features/canvas.css +2 -2
- scitex/{fig → canvas}/editor/flask_editor/static/css/features/panel-grid.css +1 -1
- scitex/{fig → canvas}/editor/flask_editor/static/js/core/api.js +3 -4
- scitex/{fig → canvas}/editor/flask_editor/static/js/editor/preview.js +5 -5
- scitex/{fig → canvas}/editor/flask_editor/templates/_html.py +3 -3
- scitex/{fig → canvas}/editor/flask_editor/templates/_scripts.py +10 -10
- scitex/{fig → canvas}/editor/flask_editor/templates/_styles.py +3 -3
- scitex/{fig → canvas}/io/__init__.py +32 -38
- scitex/{fig → canvas}/io/_bundle.py +217 -154
- scitex/{fig → canvas}/io/_canvas.py +1 -1
- scitex/{fig → canvas}/io/_data.py +1 -1
- scitex/{fig → canvas}/io/_export.py +1 -1
- scitex/{fig → canvas}/io/_load.py +1 -1
- scitex/{fig → canvas}/io/_panel.py +1 -1
- scitex/{fig → canvas}/io/_save.py +1 -1
- scitex/{fig → canvas}/model/__init__.py +1 -1
- scitex/{fig → canvas}/model/_annotations.py +1 -1
- scitex/{fig → canvas}/model/_axes.py +1 -1
- scitex/{fig → canvas}/model/_figure.py +1 -1
- scitex/{fig → canvas}/model/_guides.py +1 -1
- scitex/{fig → canvas}/model/_plot.py +1 -1
- scitex/{fig → canvas}/model/_styles.py +1 -1
- scitex/{fig → canvas}/utils/__init__.py +1 -1
- scitex/cli/convert.py +10 -6
- scitex/diagram/README.md +7 -7
- scitex/io/__init__.py +7 -19
- scitex/io/_load.py +15 -19
- scitex/io/_load_modules/_canvas.py +2 -2
- scitex/io/_load_modules/_con.py +5 -5
- scitex/io/_load_modules/_eeg.py +16 -12
- scitex/io/_save.py +11 -16
- scitex/io/_save_modules/__init__.py +6 -10
- scitex/io/_save_modules/_canvas.py +3 -3
- scitex/io/_save_modules/_plot_bundle.py +112 -0
- scitex/io/_save_modules/{_pltz_stx.py → _plot_scitex.py} +7 -7
- scitex/io/_save_modules/_stx_bundle.py +16 -16
- scitex/io/bundle/README.md +89 -80
- scitex/{fts/_bundle/_FTS.py → io/bundle/_Bundle.py} +197 -95
- scitex/io/bundle/__init__.py +67 -35
- scitex/{fts/_bundle → io/bundle}/_children.py +32 -40
- scitex/io/bundle/_core.py +184 -97
- scitex/{fts/_bundle/_dataclasses/_Node.py → io/bundle/_dataclasses/_Spec.py} +29 -23
- scitex/{fts/_bundle/_dataclasses/_NodeRefs.py → io/bundle/_dataclasses/_SpecRefs.py} +6 -6
- scitex/{fts/_bundle → io/bundle}/_dataclasses/__init__.py +4 -4
- scitex/{fts/_bundle → io/bundle}/_loader.py +19 -19
- scitex/io/bundle/_manifest.py +99 -0
- scitex/{fts/_bundle → io/bundle}/_mpl_helpers.py +119 -28
- scitex/io/bundle/_nested.py +113 -100
- scitex/{fts/_bundle → io/bundle}/_saver.py +13 -14
- scitex/{fts/_bundle → io/bundle}/_storage.py +3 -3
- scitex/io/bundle/_types.py +41 -16
- scitex/{fts/_bundle → io/bundle}/_validation.py +20 -18
- scitex/io/bundle/_zip.py +21 -31
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_backend/_parser.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Annotations.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Axes.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Figure.py +1 -1
- scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Guides.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Plot.py +1 -1
- scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Styles.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_plot/_utils/_plot_layout.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/__init__.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/_app.py +1 -1
- scitex/{fts/_tables → io/bundle/kinds/_table}/_latex/_export.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_figure_exporter.py +1 -1
- scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_table_exporter.py +1 -1
- scitex/io/bundle/schemas/__init__.py +30 -0
- scitex/parallel/_run.py +5 -4
- scitex/path/_find.py +60 -83
- scitex/path/_get_module_path.py +23 -21
- scitex/path/_get_spath.py +6 -27
- scitex/path/_getsize.py +23 -9
- scitex/path/_increment_version.py +31 -38
- scitex/path/_mk_spath.py +26 -29
- scitex/path/_path.py +5 -12
- scitex/path/_split.py +27 -15
- scitex/path/_this_path.py +23 -9
- scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +2 -1
- scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +2 -2
- scitex/plt/gallery/_generate.py +76 -50
- scitex/plt/io/__init__.py +17 -19
- scitex/plt/io/_bundle.py +99 -52
- scitex/plt/io/_layered_bundle.py +303 -168
- scitex/plt/utils/_csv_column_naming.py +250 -118
- scitex/schema/__init__.py +69 -73
- scitex/schema/_canvas.py +1 -1
- scitex/schema/_stats.py +2 -2
- scitex/stats/__init__.py +30 -33
- scitex/stats/_schema.py +1 -1
- scitex/stats/io/__init__.py +10 -11
- scitex/stats/io/_bundle.py +16 -16
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/METADATA +190 -73
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/RECORD +237 -360
- scitex/fig/editor/_defaults.py +0 -300
- scitex/fig/editor/edit/panel_loader.py +0 -232
- scitex/fig/editor/flask_editor/_bbox.py +0 -1299
- scitex/fig/editor/flask_editor/_core.py +0 -1429
- scitex/fig/editor/flask_editor/_renderer.py +0 -813
- scitex/fig/editor/flask_editor/static/css/features/canvas.css +0 -176
- scitex/fts/README.md +0 -262
- scitex/fts/TODO.md +0 -66
- scitex/fts/__init__.py +0 -90
- scitex/fts/_bundle/README_IN_BUNDLE.md +0 -102
- scitex/fts/_bundle/__init__.py +0 -38
- scitex/fts/_bundle/_utils/__init__.py +0 -55
- scitex/fts/_bundle/_utils/_const.py +0 -26
- scitex/fts/_bundle/_utils/_errors.py +0 -73
- scitex/fts/_bundle/_utils/_generate.py +0 -21
- scitex/fts/_bundle/_utils/_types.py +0 -76
- scitex/fts/_bundle/_zipbundle.py +0 -165
- scitex/fts/_fig/__init__.py +0 -22
- scitex/fts/_fig/_backend/_parser.py +0 -188
- scitex/fts/_fig/_editor/__init__.py +0 -14
- scitex/fts/_fig/_editor/_cui/__init__.py +0 -33
- scitex/fts/_fig/_editor/_cui/_backend_detector.py +0 -39
- scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +0 -366
- scitex/fts/_fig/_editor/_cui/_editor_launcher.py +0 -175
- scitex/fts/_fig/_editor/_cui/_manual_handler.py +0 -52
- scitex/fts/_fig/_editor/_cui/_path_resolver.py +0 -66
- scitex/fts/_fig/_editor/_gui/__init__.py +0 -11
- scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +0 -20
- scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +0 -664
- scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +0 -79
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +0 -41
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +0 -16
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +0 -85
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +0 -217
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +0 -93
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +0 -57
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +0 -112
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +0 -59
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +0 -212
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +0 -190
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +0 -59
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +0 -45
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +0 -95
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +0 -101
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +0 -138
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +0 -31
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +0 -7
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +0 -56
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +0 -78
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +0 -314
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +0 -107
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +0 -54
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +0 -172
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +0 -258
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +0 -48
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +0 -71
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +0 -288
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +0 -143
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +0 -245
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +0 -992
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +0 -339
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +0 -286
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +0 -371
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +0 -293
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +0 -426
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +0 -152
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +0 -265
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +0 -184
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +0 -57
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +0 -100
- scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +0 -34
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +0 -124
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +0 -851
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +0 -4932
- scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +0 -1657
- scitex/fts/_fig/_editor/_gui/_flask_editor.py +0 -36
- scitex/fts/_fig/_models/_Annotations.py +0 -115
- scitex/fts/_fig/_models/_Axes.py +0 -152
- scitex/fts/_fig/_models/_Figure.py +0 -138
- scitex/fts/_fig/_models/_Plot.py +0 -123
- scitex/fts/_fig/_utils/_plot_layout.py +0 -397
- scitex/fts/_kinds/_figure/_composite.py +0 -345
- scitex/fts/_kinds/_plot/_backend/__init__.py +0 -53
- scitex/fts/_kinds/_plot/_backend/_export.py +0 -165
- scitex/fts/_kinds/_plot/_backend/_render.py +0 -538
- scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +0 -46
- scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +0 -82
- scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +0 -441
- scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +0 -52
- scitex/fts/_kinds/_plot/_dataclasses/__init__.py +0 -47
- scitex/fts/_kinds/_plot/_models/_Guides.py +0 -104
- scitex/fts/_kinds/_plot/_models/_Styles.py +0 -245
- scitex/fts/_kinds/_plot/_models/__init__.py +0 -80
- scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +0 -156
- scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +0 -43
- scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +0 -38
- scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +0 -36
- scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +0 -60
- scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +0 -30
- scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +0 -61
- scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +0 -57
- scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +0 -30
- scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +0 -121
- scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +0 -36
- scitex/fts/_kinds/_plot/_utils/__init__.py +0 -129
- scitex/fts/_kinds/_plot/_utils/_auto_layout.py +0 -127
- scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +0 -111
- scitex/fts/_kinds/_plot/_utils/_const_sizes.py +0 -48
- scitex/fts/_kinds/_plot/_utils/_convert_coords.py +0 -77
- scitex/fts/_kinds/_plot/_utils/_get_template.py +0 -178
- scitex/fts/_kinds/_plot/_utils/_normalize.py +0 -73
- scitex/fts/_kinds/_plot/_utils/_validate.py +0 -197
- scitex/fts/_kinds/_table/_latex/_export.py +0 -279
- scitex/fts/_stats/__init__.py +0 -48
- scitex/fts/_stats/_dataclasses/_Stats.py +0 -423
- scitex/fts/_stats/_dataclasses/__init__.py +0 -48
- scitex/fts/_tables/__init__.py +0 -65
- scitex/fts/_tables/_latex/__init__.py +0 -93
- scitex/fts/_tables/_latex/_editor/__init__.py +0 -11
- scitex/fts/_tables/_latex/_editor/_app.py +0 -725
- scitex/fts/_tables/_latex/_figure_exporter.py +0 -153
- scitex/fts/_tables/_latex/_stats_formatter.py +0 -274
- scitex/fts/_tables/_latex/_table_exporter.py +0 -362
- scitex/fts/_tables/_latex/_utils.py +0 -369
- scitex/fts/_tables/_latex/_validator.py +0 -445
- scitex/io/_save_modules/_pltz_bundle.py +0 -356
- /scitex/{fig → canvas}/README.md +0 -0
- /scitex/{fig → canvas}/backend/__init__.py +0 -0
- /scitex/{fig → canvas}/backend/_export.py +0 -0
- /scitex/{fig → canvas}/backend/_render.py +0 -0
- /scitex/{fig → canvas}/docs/CANVAS_ARCHITECTURE.md +0 -0
- /scitex/{fig → canvas}/editor/__init__.py +0 -0
- /scitex/{fig → canvas}/editor/_dearpygui_editor.py +0 -0
- /scitex/{fig → canvas}/editor/_flask_editor.py +0 -0
- /scitex/{fig → canvas}/editor/_mpl_editor.py +0 -0
- /scitex/{fig → canvas}/editor/_qt_editor.py +0 -0
- /scitex/{fig → canvas}/editor/_tkinter_editor.py +0 -0
- /scitex/{fig → canvas}/editor/edit/backend_detector.py +0 -0
- /scitex/{fig → canvas}/editor/edit/manual_handler.py +0 -0
- /scitex/{fig → canvas}/editor/edit/path_resolver.py +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/__init__.py +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/_plotter.py +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/_utils.py +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/base/reset.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/base/typography.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/base/variables.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/buttons.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/context-menu.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/dropdown.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/forms.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/modal.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/components/sections.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/element-inspector.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/loading.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/overlay.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/selection.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/features/statistics.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/index.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/container.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/controls.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/preview.css +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/axis.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/basic.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/distribute.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/canvas.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/dragging.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/resize.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/selection.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/core/state.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/core/utils.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/dev/element-inspector.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/bbox.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/element-drag.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/overlay.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/main.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/context-menu.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/keyboard.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/controls.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/download.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/help.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/theme.js +0 -0
- /scitex/{fig → canvas}/editor/flask_editor/templates/__init__.py +0 -0
- /scitex/{fig → canvas}/io/_directory.py +0 -0
- /scitex/{fig → canvas}/model/_plot_types.py +0 -0
- /scitex/{fig → canvas}/utils/_defaults.py +0 -0
- /scitex/{fig → canvas}/utils/_validate.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_conversion/__init__.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_conversion/_bundle2dict.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_conversion/_dict2bundle.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_Axes.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_BBox.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_ColumnDef.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataFormat.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataInfo.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataSource.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_dataclasses/_SizeMM.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_extractors/__init__.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_bar.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_line.py +0 -0
- /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_scatter.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_figure/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_figure}/_composite.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_plot/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_export.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_render.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_ChannelEncoding.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Encoding.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Theme.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_TraceEncoding.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_bar.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_box.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_distribution.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_errorbar.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_histogram.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_image.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_line.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_scatter.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_seaborn.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_violin.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/__init__.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_auto_layout.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_calc_bounds.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_const_sizes.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_convert_coords.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_get_template.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_normalize.py +0 -0
- /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_validate.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_shape/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_stats/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/_Stats.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/__init__.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_stats_formatter.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_utils.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_validator.py +0 -0
- /scitex/{fts/_kinds → io/bundle/kinds}/_text/__init__.py +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/data_info.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/encoding.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/node.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/render_manifest.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/stats.schema.json +0 -0
- /scitex/{fts/_schemas → io/bundle/schemas}/theme.schema.json +0 -0
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/WHEEL +0 -0
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/entry_points.txt +0 -0
- {scitex-2.10.3.dist-info → scitex-2.11.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Main Entry Point
|
|
3
|
-
* Initializes all modules and sets up the Flask figure editor
|
|
4
|
-
*
|
|
5
|
-
* Module Structure:
|
|
6
|
-
* - core/: State management, utilities, API communication
|
|
7
|
-
* - canvas/: Canvas view, panel dragging, resizing, selection
|
|
8
|
-
* - editor/: Preview management, element detection, overlay rendering
|
|
9
|
-
* - alignment/: Panel alignment (basic and axis-based)
|
|
10
|
-
* - shortcuts/: Keyboard shortcuts and context menus
|
|
11
|
-
* - ui/: Form controls, downloads, help, theme
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
// ============================================================================
|
|
15
|
-
// Initialization
|
|
16
|
-
// ============================================================================
|
|
17
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
18
|
-
console.log('Flask Figure Editor initializing...');
|
|
19
|
-
|
|
20
|
-
// Initialize theme
|
|
21
|
-
initializeTheme();
|
|
22
|
-
|
|
23
|
-
// Initialize form controls
|
|
24
|
-
initializeControls();
|
|
25
|
-
|
|
26
|
-
// Load initial preview
|
|
27
|
-
loadInitialPreview();
|
|
28
|
-
|
|
29
|
-
// Setup resize observer for overlay
|
|
30
|
-
setupResizeObserver();
|
|
31
|
-
|
|
32
|
-
// Setup field-to-element sync
|
|
33
|
-
setupFieldToElementSync();
|
|
34
|
-
|
|
35
|
-
console.log('Flask Figure Editor initialized');
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
// ============================================================================
|
|
39
|
-
// Form Controls Initialization
|
|
40
|
-
// ============================================================================
|
|
41
|
-
function initializeControls() {
|
|
42
|
-
// Labels - Title
|
|
43
|
-
const titleInput = document.getElementById('title');
|
|
44
|
-
if (titleInput) titleInput.addEventListener('input', scheduleUpdate);
|
|
45
|
-
|
|
46
|
-
// Labels - Caption
|
|
47
|
-
const captionInput = document.getElementById('caption');
|
|
48
|
-
if (captionInput) captionInput.addEventListener('input', scheduleUpdate);
|
|
49
|
-
|
|
50
|
-
// Labels - Axis
|
|
51
|
-
const xlabelInput = document.getElementById('xlabel');
|
|
52
|
-
const ylabelInput = document.getElementById('ylabel');
|
|
53
|
-
if (xlabelInput) xlabelInput.addEventListener('input', scheduleUpdate);
|
|
54
|
-
if (ylabelInput) ylabelInput.addEventListener('input', scheduleUpdate);
|
|
55
|
-
|
|
56
|
-
// Axis limits
|
|
57
|
-
['xmin', 'xmax', 'ymin', 'ymax'].forEach(id => {
|
|
58
|
-
const input = document.getElementById(id);
|
|
59
|
-
if (input) input.addEventListener('input', scheduleUpdate);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Traces
|
|
63
|
-
updateTracesList();
|
|
64
|
-
|
|
65
|
-
// Legend
|
|
66
|
-
const legendVisibleInput = document.getElementById('legend_visible');
|
|
67
|
-
if (legendVisibleInput) legendVisibleInput.addEventListener('change', scheduleUpdate);
|
|
68
|
-
|
|
69
|
-
const legendLocInput = document.getElementById('legend_loc');
|
|
70
|
-
if (legendLocInput) {
|
|
71
|
-
legendLocInput.addEventListener('change', function() {
|
|
72
|
-
toggleCustomLegendPosition();
|
|
73
|
-
scheduleUpdate();
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Axis and Ticks - X Axis (Bottom)
|
|
78
|
-
['x_n_ticks', 'hide_x_ticks', 'x_tick_fontsize', 'x_tick_direction', 'x_tick_length', 'x_tick_width'].forEach(id => {
|
|
79
|
-
const input = document.getElementById(id);
|
|
80
|
-
if (input) input.addEventListener('change', scheduleUpdate);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// X Axis (Top)
|
|
84
|
-
['show_x_top', 'x_top_mirror'].forEach(id => {
|
|
85
|
-
const input = document.getElementById(id);
|
|
86
|
-
if (input) input.addEventListener('change', scheduleUpdate);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Y Axis (Left)
|
|
90
|
-
['y_n_ticks', 'hide_y_ticks', 'y_tick_fontsize', 'y_tick_direction', 'y_tick_length', 'y_tick_width'].forEach(id => {
|
|
91
|
-
const input = document.getElementById(id);
|
|
92
|
-
if (input) input.addEventListener('change', scheduleUpdate);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// Y Axis (Right)
|
|
96
|
-
['show_y_right', 'y_right_mirror'].forEach(id => {
|
|
97
|
-
const input = document.getElementById(id);
|
|
98
|
-
if (input) input.addEventListener('change', scheduleUpdate);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// Spines
|
|
102
|
-
['hide_bottom_spine', 'hide_left_spine'].forEach(id => {
|
|
103
|
-
const input = document.getElementById(id);
|
|
104
|
-
if (input) input.addEventListener('change', scheduleUpdate);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// Z Axis (3D)
|
|
108
|
-
['hide_z_ticks', 'z_n_ticks', 'z_tick_fontsize', 'z_tick_direction'].forEach(id => {
|
|
109
|
-
const input = document.getElementById(id);
|
|
110
|
-
if (input) input.addEventListener('change', scheduleUpdate);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// Style
|
|
114
|
-
['grid', 'hide_top_spine', 'hide_right_spine', 'axis_width', 'axis_fontsize'].forEach(id => {
|
|
115
|
-
const input = document.getElementById(id);
|
|
116
|
-
if (input) input.addEventListener('change', scheduleUpdate);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// Initialize background type from overrides
|
|
120
|
-
if (overrides.transparent) {
|
|
121
|
-
setBackgroundType('transparent');
|
|
122
|
-
} else if (overrides.facecolor === 'black') {
|
|
123
|
-
setBackgroundType('black');
|
|
124
|
-
} else {
|
|
125
|
-
setBackgroundType('white');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Dimensions (convert from inches in metadata to mm by default)
|
|
129
|
-
if (overrides.fig_size) {
|
|
130
|
-
// fig_size is in inches in the JSON - convert to mm for default display
|
|
131
|
-
const widthInput = document.getElementById('fig_width');
|
|
132
|
-
const heightInput = document.getElementById('fig_height');
|
|
133
|
-
if (widthInput && heightInput) {
|
|
134
|
-
widthInput.value = (overrides.fig_size[0] * INCH_TO_MM).toFixed(1);
|
|
135
|
-
heightInput.value = (overrides.fig_size[1] * INCH_TO_MM).toFixed(1);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Default unit is mm, which is already set in HTML and JS state
|
|
140
|
-
|
|
141
|
-
// Setup color sync for selected element property inputs
|
|
142
|
-
setupColorSync('trace-color-picker', 'trace-color-text');
|
|
143
|
-
setupColorSync('scatter-color-picker', 'scatter-color-text');
|
|
144
|
-
setupColorSync('fill-color-picker', 'fill-color-text');
|
|
145
|
-
|
|
146
|
-
// Mark initialization complete - now background changes will trigger updates
|
|
147
|
-
initializingBackground = false;
|
|
148
|
-
|
|
149
|
-
console.log('Controls initialized');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// ============================================================================
|
|
153
|
-
// Resize Observer Setup
|
|
154
|
-
// ============================================================================
|
|
155
|
-
function setupResizeObserver() {
|
|
156
|
-
// Add resize handler to update overlay when window/image size changes
|
|
157
|
-
window.addEventListener('resize', updateOverlay);
|
|
158
|
-
|
|
159
|
-
// Use ResizeObserver to detect when the preview container changes size
|
|
160
|
-
const previewContainer = document.getElementById('preview-container');
|
|
161
|
-
if (previewContainer && typeof ResizeObserver !== 'undefined') {
|
|
162
|
-
const resizeObserver = new ResizeObserver(() => {
|
|
163
|
-
updateOverlay();
|
|
164
|
-
});
|
|
165
|
-
resizeObserver.observe(previewContainer);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// ============================================================================
|
|
170
|
-
// Field-to-Element Synchronization
|
|
171
|
-
// ============================================================================
|
|
172
|
-
function setupFieldToElementSync() {
|
|
173
|
-
// Map field IDs to element names
|
|
174
|
-
const fieldToElement = {
|
|
175
|
-
// Title, Labels & Caption section
|
|
176
|
-
'title': 'title',
|
|
177
|
-
'caption': 'caption',
|
|
178
|
-
'xlabel': 'xlabel',
|
|
179
|
-
'ylabel': 'ylabel',
|
|
180
|
-
|
|
181
|
-
// Axis & Ticks section
|
|
182
|
-
'xmin': 'xaxis',
|
|
183
|
-
'xmax': 'xaxis',
|
|
184
|
-
'ymin': 'yaxis',
|
|
185
|
-
'ymax': 'yaxis',
|
|
186
|
-
'x_n_ticks': 'xaxis',
|
|
187
|
-
'y_n_ticks': 'yaxis',
|
|
188
|
-
'hide_x_ticks': 'xaxis',
|
|
189
|
-
'hide_y_ticks': 'yaxis',
|
|
190
|
-
|
|
191
|
-
// Legend section
|
|
192
|
-
'legend_visible': 'legend',
|
|
193
|
-
'legend_loc': 'legend',
|
|
194
|
-
'legend_frameon': 'legend',
|
|
195
|
-
'legend_fontsize': 'legend',
|
|
196
|
-
'legend_ncols': 'legend',
|
|
197
|
-
'legend_x': 'legend',
|
|
198
|
-
'legend_y': 'legend',
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
// Add focus listeners to all mapped fields
|
|
202
|
-
for (const [fieldId, elementName] of Object.entries(fieldToElement)) {
|
|
203
|
-
const field = document.getElementById(fieldId);
|
|
204
|
-
if (field) {
|
|
205
|
-
field.addEventListener('focus', function() {
|
|
206
|
-
// Find the element in bboxes - for multi-panel, check ax_00 first
|
|
207
|
-
let foundElement = elementName;
|
|
208
|
-
if (elementBboxes[`ax_00_${elementName}`]) {
|
|
209
|
-
foundElement = `ax_00_${elementName}`;
|
|
210
|
-
} else if (elementBboxes[elementName]) {
|
|
211
|
-
foundElement = elementName;
|
|
212
|
-
} else {
|
|
213
|
-
// Try to find with axis prefix (e.g., ax_00_title)
|
|
214
|
-
for (const key of Object.keys(elementBboxes)) {
|
|
215
|
-
if (key.endsWith(`_${elementName}`)) {
|
|
216
|
-
foundElement = key;
|
|
217
|
-
break;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (elementBboxes[foundElement]) {
|
|
223
|
-
hoveredElement = foundElement;
|
|
224
|
-
updateOverlay();
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
// Also handle mouseenter for hover feedback
|
|
229
|
-
field.addEventListener('mouseenter', function() {
|
|
230
|
-
const helpText = this.getAttribute('title') || this.getAttribute('placeholder');
|
|
231
|
-
if (helpText) {
|
|
232
|
-
setStatus(helpText, false);
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
field.addEventListener('mouseleave', function() {
|
|
237
|
-
setStatus('Ready', false);
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// ============================================================================
|
|
244
|
-
// Traces List Update
|
|
245
|
-
// ============================================================================
|
|
246
|
-
function updateTracesList() {
|
|
247
|
-
const container = document.getElementById('traces-list');
|
|
248
|
-
if (!container) return;
|
|
249
|
-
|
|
250
|
-
container.innerHTML = '';
|
|
251
|
-
if (!traces || traces.length === 0) return;
|
|
252
|
-
|
|
253
|
-
traces.forEach((trace, idx) => {
|
|
254
|
-
const item = document.createElement('div');
|
|
255
|
-
item.className = 'trace-item';
|
|
256
|
-
item.innerHTML = `
|
|
257
|
-
<label>${trace.label || `Trace ${idx}`}</label>
|
|
258
|
-
<input type="color" value="${trace.color || '#000000'}" onchange="updateTraceColor(${idx}, this.value)">
|
|
259
|
-
<select onchange="updateTraceStyle(${idx}, this.value)">
|
|
260
|
-
<option value="-" ${trace.linestyle === '-' ? 'selected' : ''}>Solid</option>
|
|
261
|
-
<option value="--" ${trace.linestyle === '--' ? 'selected' : ''}>Dashed</option>
|
|
262
|
-
<option value="-." ${trace.linestyle === '-.' ? 'selected' : ''}>Dash-dot</option>
|
|
263
|
-
<option value=":" ${trace.linestyle === ':' ? 'selected' : ''}>Dotted</option>
|
|
264
|
-
</select>
|
|
265
|
-
`;
|
|
266
|
-
container.appendChild(item);
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function updateTraceColor(idx, color) {
|
|
271
|
-
if (traces[idx]) {
|
|
272
|
-
traces[idx].color = color;
|
|
273
|
-
scheduleUpdate();
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function updateTraceStyle(idx, style) {
|
|
278
|
-
if (traces[idx]) {
|
|
279
|
-
traces[idx].linestyle = style;
|
|
280
|
-
scheduleUpdate();
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// ============================================================================
|
|
285
|
-
// Hover System Initialization (for SVG mode)
|
|
286
|
-
// ============================================================================
|
|
287
|
-
function initHoverSystemForElement(el) {
|
|
288
|
-
// Initialize hover detection for inline SVG elements
|
|
289
|
-
if (!el) return;
|
|
290
|
-
|
|
291
|
-
el.addEventListener('mousemove', (e) => {
|
|
292
|
-
// Find element at cursor position
|
|
293
|
-
// This would require SVG-specific hit detection
|
|
294
|
-
// For now, just update overlay
|
|
295
|
-
updateOverlay();
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
el.addEventListener('click', (e) => {
|
|
299
|
-
// Select element on click
|
|
300
|
-
// This would require SVG-specific hit detection
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// ============================================================================
|
|
305
|
-
// Canvas Item Interaction (Multi-Panel)
|
|
306
|
-
// ============================================================================
|
|
307
|
-
function initCanvasItemInteraction(item, panelIdx, panelName) {
|
|
308
|
-
const container = item.querySelector('.panel-card-container');
|
|
309
|
-
if (!container) return;
|
|
310
|
-
|
|
311
|
-
const img = container.querySelector('img');
|
|
312
|
-
const overlay = container.querySelector('svg');
|
|
313
|
-
if (!img || !overlay) return;
|
|
314
|
-
|
|
315
|
-
// Wait for image to load to get dimensions
|
|
316
|
-
img.addEventListener('load', () => {
|
|
317
|
-
overlay.setAttribute('width', img.offsetWidth);
|
|
318
|
-
overlay.setAttribute('height', img.offsetHeight);
|
|
319
|
-
overlay.style.width = img.offsetWidth + 'px';
|
|
320
|
-
overlay.style.height = img.offsetHeight + 'px';
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
// Mousemove for hover detection (accounting for object-fit:contain letterboxing)
|
|
324
|
-
container.addEventListener('mousemove', (e) => {
|
|
325
|
-
const panelCache = panelBboxesCache[panelName];
|
|
326
|
-
if (!panelCache) return;
|
|
327
|
-
|
|
328
|
-
const rect = img.getBoundingClientRect();
|
|
329
|
-
const dims = getObjectFitContainDimensions(img);
|
|
330
|
-
|
|
331
|
-
// Mouse position relative to container
|
|
332
|
-
const x = e.clientX - rect.left;
|
|
333
|
-
const y = e.clientY - rect.top;
|
|
334
|
-
|
|
335
|
-
// Adjust for letterbox offset to get position relative to actual rendered image
|
|
336
|
-
const imgRelX = x - dims.offsetX;
|
|
337
|
-
const imgRelY = y - dims.offsetY;
|
|
338
|
-
|
|
339
|
-
// Check if click is within rendered image bounds
|
|
340
|
-
if (imgRelX < 0 || imgRelY < 0 || imgRelX > dims.displayWidth || imgRelY > dims.displayHeight) {
|
|
341
|
-
// Outside rendered image area (in letterbox region)
|
|
342
|
-
if (panelHoveredElement !== null) {
|
|
343
|
-
panelHoveredElement = null;
|
|
344
|
-
updatePanelOverlay(overlay, panelCache.bboxes, panelCache.imgSize, rect.width, rect.height, null, null, img);
|
|
345
|
-
}
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Scale to original image coordinates
|
|
350
|
-
const scaleX = panelCache.imgSize.width / dims.displayWidth;
|
|
351
|
-
const scaleY = panelCache.imgSize.height / dims.displayHeight;
|
|
352
|
-
const imgX = imgRelX * scaleX;
|
|
353
|
-
const imgY = imgRelY * scaleY;
|
|
354
|
-
|
|
355
|
-
const element = findElementInPanelAt(imgX, imgY, panelCache.bboxes);
|
|
356
|
-
if (element !== panelHoveredElement || activePanelCard !== item) {
|
|
357
|
-
panelHoveredElement = element;
|
|
358
|
-
activePanelCard = item;
|
|
359
|
-
updatePanelOverlay(overlay, panelCache.bboxes, panelCache.imgSize, rect.width, rect.height, element, selectedElement, img);
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
// Mouseleave to clear hover
|
|
364
|
-
container.addEventListener('mouseleave', () => {
|
|
365
|
-
panelHoveredElement = null;
|
|
366
|
-
activePanelCard = null;
|
|
367
|
-
const panelCache = panelBboxesCache[panelName];
|
|
368
|
-
if (panelCache) {
|
|
369
|
-
updatePanelOverlay(overlay, panelCache.bboxes, panelCache.imgSize, img.offsetWidth, img.offsetHeight, null, selectedElement, img);
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
// Mousedown to start element drag (ONLY for legends and panel letters)
|
|
374
|
-
container.addEventListener('mousedown', (e) => {
|
|
375
|
-
if (panelHoveredElement && isDraggableElement(panelHoveredElement, panelBboxesCache[panelName]?.bboxes)) {
|
|
376
|
-
// Only allow dragging of legends and panel letters (scientific rigor)
|
|
377
|
-
startElementDrag(e, panelHoveredElement, panelName, img, panelBboxesCache[panelName].bboxes);
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
// Click to select element (accounting for object-fit:contain letterboxing)
|
|
382
|
-
container.addEventListener('click', (e) => {
|
|
383
|
-
// Recalculate element at click position (in case hover didn't detect it)
|
|
384
|
-
const panelCache = panelBboxesCache[panelName];
|
|
385
|
-
if (!panelCache) return;
|
|
386
|
-
|
|
387
|
-
const rect = img.getBoundingClientRect();
|
|
388
|
-
const dims = getObjectFitContainDimensions(img);
|
|
389
|
-
|
|
390
|
-
// Mouse position relative to container
|
|
391
|
-
const x = e.clientX - rect.left;
|
|
392
|
-
const y = e.clientY - rect.top;
|
|
393
|
-
|
|
394
|
-
// Adjust for letterbox offset
|
|
395
|
-
const imgRelX = x - dims.offsetX;
|
|
396
|
-
const imgRelY = y - dims.offsetY;
|
|
397
|
-
|
|
398
|
-
// Check if click is within rendered image bounds
|
|
399
|
-
if (imgRelX >= 0 && imgRelY >= 0 && imgRelX <= dims.displayWidth && imgRelY <= dims.displayHeight) {
|
|
400
|
-
// Scale to original image coordinates
|
|
401
|
-
const scaleX = panelCache.imgSize.width / dims.displayWidth;
|
|
402
|
-
const scaleY = panelCache.imgSize.height / dims.displayHeight;
|
|
403
|
-
const imgX = imgRelX * scaleX;
|
|
404
|
-
const imgY = imgRelY * scaleY;
|
|
405
|
-
|
|
406
|
-
const element = findElementInPanelAt(imgX, imgY, panelCache.bboxes);
|
|
407
|
-
if (element) {
|
|
408
|
-
loadPanelForEditing(panelName);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
// Drag support for repositioning
|
|
414
|
-
initPanelDrag(item, panelName);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// ============================================================================
|
|
418
|
-
// Panel Card Interaction (for panel grid view - if used)
|
|
419
|
-
// ============================================================================
|
|
420
|
-
function initPanelCardInteraction(card, panelIdx, panelName) {
|
|
421
|
-
// Similar to initCanvasItemInteraction but for panel grid cards
|
|
422
|
-
// Simplified version - delegates to initCanvasItemInteraction
|
|
423
|
-
initCanvasItemInteraction(card, panelIdx, panelName);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
console.log('main.js loaded');
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Context Menu
|
|
3
|
-
* Right-click context menu for panel operations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// ============================================================================
|
|
7
|
-
// Show Context Menu
|
|
8
|
-
// ============================================================================
|
|
9
|
-
function showContextMenu(e, panelName) {
|
|
10
|
-
e.preventDefault();
|
|
11
|
-
hideContextMenu();
|
|
12
|
-
|
|
13
|
-
const selectedCount = document.querySelectorAll('.panel-canvas-item.selected').length;
|
|
14
|
-
const hasSelection = selectedCount > 0;
|
|
15
|
-
|
|
16
|
-
const menu = document.createElement('div');
|
|
17
|
-
menu.id = 'canvas-context-menu';
|
|
18
|
-
menu.className = 'context-menu';
|
|
19
|
-
menu.innerHTML = `
|
|
20
|
-
<div class="context-menu-item" onclick="selectAllPanels(); hideContextMenu();">
|
|
21
|
-
<span class="context-menu-icon">⬚</span> Select All <span class="context-menu-shortcut">Ctrl+A</span>
|
|
22
|
-
</div>
|
|
23
|
-
<div class="context-menu-item ${!hasSelection ? 'disabled' : ''}" onclick="${hasSelection ? 'deselectAllPanels(); hideContextMenu();' : ''}">
|
|
24
|
-
<span class="context-menu-icon">○</span> Deselect All <span class="context-menu-shortcut">Esc</span>
|
|
25
|
-
</div>
|
|
26
|
-
<div class="context-menu-divider"></div>
|
|
27
|
-
<div class="context-menu-item ${!hasSelection ? 'disabled' : ''}" onclick="${hasSelection ? 'bringPanelToFront(); hideContextMenu();' : ''}">
|
|
28
|
-
<span class="context-menu-icon">↑</span> Bring to Front <span class="context-menu-shortcut">Alt+F</span>
|
|
29
|
-
</div>
|
|
30
|
-
<div class="context-menu-item ${!hasSelection ? 'disabled' : ''}" onclick="${hasSelection ? 'sendPanelToBack(); hideContextMenu();' : ''}">
|
|
31
|
-
<span class="context-menu-icon">↓</span> Send to Back <span class="context-menu-shortcut">Alt+B</span>
|
|
32
|
-
</div>
|
|
33
|
-
<div class="context-menu-divider"></div>
|
|
34
|
-
<div class="context-menu-submenu">
|
|
35
|
-
<div class="context-menu-item">
|
|
36
|
-
<span class="context-menu-icon">≡</span> Align <span class="context-menu-arrow">▶</span>
|
|
37
|
-
</div>
|
|
38
|
-
<div class="context-submenu">
|
|
39
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "alignPanels('left'); hideContextMenu();" : ''}">Left</div>
|
|
40
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "alignPanels('right'); hideContextMenu();" : ''}">Right</div>
|
|
41
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "alignPanels('top'); hideContextMenu();" : ''}">Top</div>
|
|
42
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "alignPanels('bottom'); hideContextMenu();" : ''}">Bottom</div>
|
|
43
|
-
<div class="context-menu-divider"></div>
|
|
44
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "alignPanels('center-h'); hideContextMenu();" : ''}">Center H</div>
|
|
45
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "alignPanels('center-v'); hideContextMenu();" : ''}">Center V</div>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
<div class="context-menu-submenu">
|
|
49
|
-
<div class="context-menu-item">
|
|
50
|
-
<span class="context-menu-icon">⊞</span> Align by Axis <span class="context-menu-arrow">▶</span>
|
|
51
|
-
</div>
|
|
52
|
-
<div class="context-submenu">
|
|
53
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "alignPanelsByAxis('left'); hideContextMenu();" : ''}">Y-Axis (Left)</div>
|
|
54
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "alignPanelsByAxis('bottom'); hideContextMenu();" : ''}">X-Axis (Bottom)</div>
|
|
55
|
-
<div class="context-menu-divider"></div>
|
|
56
|
-
<div class="context-menu-item ${selectedCount < 2 ? 'disabled' : ''}" onclick="${selectedCount >= 2 ? "stackPanelsVertically(); hideContextMenu();" : ''}">Stack Vertically</div>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
<div class="context-menu-submenu">
|
|
60
|
-
<div class="context-menu-item">
|
|
61
|
-
<span class="context-menu-icon">⇔</span> Distribute <span class="context-menu-arrow">▶</span>
|
|
62
|
-
</div>
|
|
63
|
-
<div class="context-submenu">
|
|
64
|
-
<div class="context-menu-item ${selectedCount < 3 ? 'disabled' : ''}" onclick="${selectedCount >= 3 ? "distributePanels('horizontal'); hideContextMenu();" : ''}">Horizontal</div>
|
|
65
|
-
<div class="context-menu-item ${selectedCount < 3 ? 'disabled' : ''}" onclick="${selectedCount >= 3 ? "distributePanels('vertical'); hideContextMenu();" : ''}">Vertical</div>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
<div class="context-menu-divider"></div>
|
|
69
|
-
<div class="context-menu-item" onclick="toggleGridVisibility(); hideContextMenu();">
|
|
70
|
-
<span class="context-menu-icon">⊞</span> Toggle Grid <span class="context-menu-shortcut">G</span>
|
|
71
|
-
</div>
|
|
72
|
-
<div class="context-menu-divider"></div>
|
|
73
|
-
<div class="context-menu-item" onclick="showShortcutHelp(); hideContextMenu();">
|
|
74
|
-
<span class="context-menu-icon">⌨</span> Keyboard Shortcuts <span class="context-menu-shortcut">?</span>
|
|
75
|
-
</div>
|
|
76
|
-
`;
|
|
77
|
-
|
|
78
|
-
// Position menu at cursor
|
|
79
|
-
menu.style.left = e.clientX + 'px';
|
|
80
|
-
menu.style.top = e.clientY + 'px';
|
|
81
|
-
|
|
82
|
-
document.body.appendChild(menu);
|
|
83
|
-
contextMenu = menu;
|
|
84
|
-
|
|
85
|
-
// Adjust position if menu goes off screen
|
|
86
|
-
const rect = menu.getBoundingClientRect();
|
|
87
|
-
if (rect.right > window.innerWidth) {
|
|
88
|
-
menu.style.left = (window.innerWidth - rect.width - 5) + 'px';
|
|
89
|
-
}
|
|
90
|
-
if (rect.bottom > window.innerHeight) {
|
|
91
|
-
menu.style.top = (window.innerHeight - rect.height - 5) + 'px';
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ============================================================================
|
|
96
|
-
// Hide Context Menu
|
|
97
|
-
// ============================================================================
|
|
98
|
-
function hideContextMenu() {
|
|
99
|
-
if (contextMenu) {
|
|
100
|
-
contextMenu.remove();
|
|
101
|
-
contextMenu = null;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// ============================================================================
|
|
106
|
-
// Event Listeners for Context Menu
|
|
107
|
-
// ============================================================================
|
|
108
|
-
|
|
109
|
-
// Close context menu on click outside
|
|
110
|
-
document.addEventListener('click', (e) => {
|
|
111
|
-
if (contextMenu && !contextMenu.contains(e.target)) {
|
|
112
|
-
hideContextMenu();
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Close context menu on Escape
|
|
117
|
-
document.addEventListener('keydown', (e) => {
|
|
118
|
-
if (e.key === 'Escape' && contextMenu) {
|
|
119
|
-
hideContextMenu();
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
// Attach context menu to canvas
|
|
124
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
125
|
-
const canvas = document.getElementById('panel-canvas');
|
|
126
|
-
if (canvas) {
|
|
127
|
-
canvas.addEventListener('contextmenu', (e) => {
|
|
128
|
-
// Check if right-click is on a panel
|
|
129
|
-
const panel = e.target.closest('.panel-canvas-item');
|
|
130
|
-
const panelName = panel ? panel.dataset.panelName : null;
|
|
131
|
-
|
|
132
|
-
// If clicking on a panel that's not selected, select it
|
|
133
|
-
if (panel && !panel.classList.contains('selected')) {
|
|
134
|
-
if (!e.ctrlKey && !e.metaKey) {
|
|
135
|
-
deselectAllPanels();
|
|
136
|
-
}
|
|
137
|
-
panel.classList.add('selected');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
showContextMenu(e, panelName);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Click on empty canvas space deselects all panels
|
|
144
|
-
canvas.addEventListener('click', (e) => {
|
|
145
|
-
// Only deselect if clicking directly on canvas background, not on a panel
|
|
146
|
-
const panel = e.target.closest('.panel-canvas-item');
|
|
147
|
-
if (!panel && !e.ctrlKey && !e.metaKey) {
|
|
148
|
-
deselectAllPanels();
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
});
|