plexora 0.0.1__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.
- plexora/__init__.py +129 -0
- plexora/__main__.py +15 -0
- plexora/_url.py +105 -0
- plexora/api/__init__.py +55 -0
- plexora/api/dataset.py +398 -0
- plexora/api/http.py +19 -0
- plexora/api/plugin.py +541 -0
- plexora/api/store.py +221 -0
- plexora/cli.py +777 -0
- plexora/client/dist/354_bundle.js +2 -0
- plexora/client/dist/354_bundle.js.LICENSE.txt +20 -0
- plexora/client/dist/418_bundle.js +2 -0
- plexora/client/dist/418_bundle.js.LICENSE.txt +1 -0
- plexora/client/dist/693b935cb1f907814be9c6199a68c217.svg +19 -0
- plexora/client/dist/713c134ff47cd328a5b711526f151082.svg +18 -0
- plexora/client/dist/770_bundle.js +1 -0
- plexora/client/dist/ff743f408972e0e96ca9153ed5ae4c83.svg +23 -0
- plexora/client/dist/vendor_bundle.js +2 -0
- plexora/client/dist/vendor_bundle.js.LICENSE.txt +308 -0
- plexora/client/external/openseadragon-bin-2.4.0/LICENSE.txt +28 -0
- plexora/client/external/openseadragon-bin-2.4.0/canvas-overlay-hd.js +140 -0
- plexora/client/external/openseadragon-bin-2.4.0/changelog.txt +501 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/.gitattributes +17 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/LICENSE.txt +116 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/Toolbar.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/fullpage.psd +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/home.psd +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/next.psd +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/previous.psd +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/rotateleft.psd +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/rotateright.psd +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/Photoshop/zoom.psd +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/README.md +9 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/fullpage_grouphover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/fullpage_hover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/fullpage_pressed.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/fullpage_rest.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/home_grouphover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/home_hover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/home_pressed.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/home_rest.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/next_grouphover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/next_hover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/next_pressed.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/next_rest.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/previous_grouphover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/previous_hover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/previous_pressed.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/previous_rest.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateleft_grouphover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateleft_hover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateleft_pressed.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateleft_rest.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateright_grouphover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateright_hover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateright_pressed.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/rotateright_rest.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomin_grouphover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomin_hover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomin_pressed.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomin_rest.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomout_grouphover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomout_hover.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomout_pressed.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-flat-toolbar-icons-master/images/zoomout_rest.png +0 -0
- plexora/client/external/openseadragon-bin-2.4.0/openseadragon-scalebar.js +562 -0
- plexora/client/src/css/import.css +474 -0
- plexora/client/src/css/main.css +903 -0
- plexora/client/src/css/openProject.css +363 -0
- plexora/client/src/css/quickView.css +166 -0
- plexora/client/src/css/tokens.css +51 -0
- plexora/client/src/css/viewer.css +1655 -0
- plexora/client/src/img/apple-touch-icon.png +0 -0
- plexora/client/src/img/favicon.ico +0 -0
- plexora/client/src/img/logo.ai +8892 -33
- plexora/client/src/img/logo.svg +1 -0
- plexora/client/src/img/logo_with_text.ai +9011 -34
- plexora/client/src/img/logo_with_text.svg +1 -0
- plexora/client/src/js/main.js +704 -0
- plexora/client/src/js/pluginRegistry.js +108 -0
- plexora/client/src/js/services/appStatus.js +286 -0
- plexora/client/src/js/services/browsePicker.js +73 -0
- plexora/client/src/js/services/dataLayer.js +400 -0
- plexora/client/src/js/services/datasetContext.js +143 -0
- plexora/client/src/js/services/glRenderer.js +143 -0
- plexora/client/src/js/services/importFormValidation.js +257 -0
- plexora/client/src/js/services/numericData.js +100 -0
- plexora/client/src/js/services/passVariablesToFrontend.js +20 -0
- plexora/client/src/js/services/simpleEventHandler.js +25 -0
- plexora/client/src/js/vendor.js +29 -0
- plexora/client/src/js/views/channelList.js +663 -0
- plexora/client/src/js/views/colorSwatchPicker.js +202 -0
- plexora/client/src/js/views/columnClassifier.js +146 -0
- plexora/client/src/js/views/coordinateField.js +133 -0
- plexora/client/src/js/views/dataSourceField.js +276 -0
- plexora/client/src/js/views/imageViewer.js +3306 -0
- plexora/client/src/js/views/miniMap.js +787 -0
- plexora/client/src/js/views/navbarControls.js +178 -0
- plexora/client/src/js/views/openProjectPage.js +239 -0
- plexora/client/src/js/views/projectEdit.js +335 -0
- plexora/client/src/js/views/quickViewLanding.js +136 -0
- plexora/client/src/js/views/rainbow.js +326 -0
- plexora/client/src/js/views/requirementsModal.js +572 -0
- plexora/client/src/js/views/rgbImageViewer.js +115 -0
- plexora/client/src/js/views/searchableSelect.js +411 -0
- plexora/client/src/js/views/segmentationProgress.js +122 -0
- plexora/client/src/js/views/toolLoader.js +747 -0
- plexora/client/src/js/views/viewerControls.js +689 -0
- plexora/client/src/js/views/viewerManager.js +434 -0
- plexora/client/src/js/views/viewerSidebar.js +1117 -0
- plexora/client/src/js/workers/tileDecoder.js +130 -0
- plexora/client/src/shaders/frag.glsl +528 -0
- plexora/client/src/shaders/vert.glsl +12 -0
- plexora/client/templates/base.html +212 -0
- plexora/client/templates/index.html +238 -0
- plexora/client/templates/open_project.html +96 -0
- plexora/client/templates/project_columns.html +86 -0
- plexora/client/templates/project_edit.html +196 -0
- plexora/client/templates/upload.html +118 -0
- plexora/connect.py +528 -0
- plexora/datasource.py +782 -0
- plexora/jupyter.py +406 -0
- plexora/notebook_env.py +232 -0
- plexora/paths.py +486 -0
- plexora/plugins/__init__.py +12 -0
- plexora/plugins/cell_explorer/__init__.py +100 -0
- plexora/plugins/cell_explorer/server/__init__.py +11 -0
- plexora/plugins/cell_explorer/server/routes.py +167 -0
- plexora/plugins/cell_explorer/server/state.py +281 -0
- plexora/plugins/cell_explorer/server/values.py +145 -0
- plexora/plugins/cell_explorer/server/variables.py +367 -0
- plexora/plugins/cell_explorer/static/cellExplorerApi.js +158 -0
- plexora/plugins/cell_explorer/static/cellExplorerColors.js +316 -0
- plexora/plugins/cell_explorer/static/cellExplorerContinuous.js +403 -0
- plexora/plugins/cell_explorer/static/cellExplorerFigureBridge.js +133 -0
- plexora/plugins/cell_explorer/static/cellExplorerLegend.js +188 -0
- plexora/plugins/cell_explorer/static/cellExplorerRoiBridge.js +822 -0
- plexora/plugins/cell_explorer/static/cellExplorerSidebarController.js +826 -0
- plexora/plugins/cell_explorer/static/cellExplorerState.js +372 -0
- plexora/plugins/cell_explorer/static/cell_explorer.css +752 -0
- plexora/plugins/cell_explorer/templates/cell_explorer/panel.html +137 -0
- plexora/plugins/figure_builder/__init__.py +125 -0
- plexora/plugins/figure_builder/server/__init__.py +7 -0
- plexora/plugins/figure_builder/server/compose.py +365 -0
- plexora/plugins/figure_builder/server/export.py +784 -0
- plexora/plugins/figure_builder/server/export_jobs.py +148 -0
- plexora/plugins/figure_builder/server/operations.py +556 -0
- plexora/plugins/figure_builder/server/pixels.py +142 -0
- plexora/plugins/figure_builder/server/provenance.py +174 -0
- plexora/plugins/figure_builder/server/render.py +278 -0
- plexora/plugins/figure_builder/server/repository.py +701 -0
- plexora/plugins/figure_builder/server/routes.py +594 -0
- plexora/plugins/figure_builder/server/schema.py +1023 -0
- plexora/plugins/figure_builder/server/sources.py +120 -0
- plexora/plugins/figure_builder/server/textmetrics.py +155 -0
- plexora/plugins/figure_builder/static/figureActions.js +363 -0
- plexora/plugins/figure_builder/static/figureBuilderApi.js +255 -0
- plexora/plugins/figure_builder/static/figureCanvas.js +2362 -0
- plexora/plugins/figure_builder/static/figureCaptureBoxes.js +369 -0
- plexora/plugins/figure_builder/static/figureCaptureDock.js +466 -0
- plexora/plugins/figure_builder/static/figureCaptureTool.js +1034 -0
- plexora/plugins/figure_builder/static/figureConfirm.js +136 -0
- plexora/plugins/figure_builder/static/figureContextBar.js +1193 -0
- plexora/plugins/figure_builder/static/figureContextMenu.js +253 -0
- plexora/plugins/figure_builder/static/figureDocumentState.js +275 -0
- plexora/plugins/figure_builder/static/figureExportUi.js +174 -0
- plexora/plugins/figure_builder/static/figureLibrary.js +247 -0
- plexora/plugins/figure_builder/static/figureQuickEdit.js +628 -0
- plexora/plugins/figure_builder/static/figureRichText.js +634 -0
- plexora/plugins/figure_builder/static/figureSceneSnapshot.js +361 -0
- plexora/plugins/figure_builder/static/figureSchema.js +218 -0
- plexora/plugins/figure_builder/static/figureSidebarController.js +1159 -0
- plexora/plugins/figure_builder/static/figureTextEditor.js +503 -0
- plexora/plugins/figure_builder/static/figureTextPanel.js +491 -0
- plexora/plugins/figure_builder/static/figureViewOptions.js +273 -0
- plexora/plugins/figure_builder/static/figureWorkspace.js +2030 -0
- plexora/plugins/figure_builder/static/figure_builder.css +3292 -0
- plexora/plugins/figure_builder/templates/figure_builder/library.html +74 -0
- plexora/plugins/figure_builder/templates/figure_builder/workspace.html +27 -0
- plexora/plugins/figure_builder/templates/figure_builder/workspace_body.html +458 -0
- plexora/plugins/gating/__init__.py +76 -0
- plexora/plugins/gating/server/__init__.py +0 -0
- plexora/plugins/gating/server/anndata_gates.py +367 -0
- plexora/plugins/gating/server/database.py +16 -0
- plexora/plugins/gating/server/model.py +320 -0
- plexora/plugins/gating/server/routes.py +235 -0
- plexora/plugins/gating/static/csvGatingList.js +947 -0
- plexora/plugins/gating/static/gating.css +289 -0
- plexora/plugins/gating/static/gatingApi.js +221 -0
- plexora/plugins/gating/static/gatingSidebarController.js +513 -0
- plexora/plugins/gating/templates/gating/legacy.html +26 -0
- plexora/plugins/gating/templates/gating/panel.html +69 -0
- plexora/plugins/roi/__init__.py +95 -0
- plexora/plugins/roi/server/__init__.py +8 -0
- plexora/plugins/roi/server/adapters.py +655 -0
- plexora/plugins/roi/server/geojson.py +267 -0
- plexora/plugins/roi/server/geometry.py +181 -0
- plexora/plugins/roi/server/mapping.py +169 -0
- plexora/plugins/roi/server/operations.py +293 -0
- plexora/plugins/roi/server/repository.py +215 -0
- plexora/plugins/roi/server/routes.py +409 -0
- plexora/plugins/roi/server/schema.py +323 -0
- plexora/plugins/roi/static/roi.css +583 -0
- plexora/plugins/roi/static/roiApi.js +177 -0
- plexora/plugins/roi/static/roiFigureBridge.js +107 -0
- plexora/plugins/roi/static/roiGeometry.js +350 -0
- plexora/plugins/roi/static/roiRenderer.js +278 -0
- plexora/plugins/roi/static/roiSidebarController.js +1038 -0
- plexora/plugins/roi/static/roiState.js +518 -0
- plexora/plugins/roi/static/roiTools.js +993 -0
- plexora/plugins/roi/templates/roi/panel.html +240 -0
- plexora/proxy.py +57 -0
- plexora/server/models/adapters/__init__.py +94 -0
- plexora/server/models/adapters/anndata_adapter.py +388 -0
- plexora/server/models/adapters/base.py +93 -0
- plexora/server/models/adapters/classify.py +192 -0
- plexora/server/models/adapters/csv_adapter.py +105 -0
- plexora/server/models/adapters/inspection.py +265 -0
- plexora/server/models/adapters/spatialdata_adapter.py +248 -0
- plexora/server/models/centroid_tiles.py +305 -0
- plexora/server/models/data_model.py +1659 -0
- plexora/server/models/database_model.py +169 -0
- plexora/server/models/project.py +1270 -0
- plexora/server/plugins.py +199 -0
- plexora/server/routes/browse_routes.py +41 -0
- plexora/server/routes/data_routes.py +294 -0
- plexora/server/routes/import_routes.py +603 -0
- plexora/server/routes/page_routes.py +139 -0
- plexora/server/routes/project_routes.py +438 -0
- plexora/server/routes/quick_view_routes.py +62 -0
- plexora/server/routes/system_routes.py +39 -0
- plexora/server/routes/tool_routes.py +418 -0
- plexora/server/utils/addHEColumns.py +11 -0
- plexora/server/utils/fast_png.py +97 -0
- plexora/server/utils/fullConversion.py +50 -0
- plexora/server/utils/native_dialog.py +168 -0
- plexora/server/utils/pre_normalization.py +47 -0
- plexora/server/utils/segmentation_pyramid.py +598 -0
- plexora/server/utils/smallestenclosingcircle.py +126 -0
- plexora/server/utils/tiffsurgeon.py +372 -0
- plexora/server_cli.py +48 -0
- plexora/test.py +0 -0
- plexora-0.0.1.dist-info/METADATA +341 -0
- plexora-0.0.1.dist-info/RECORD +248 -0
- plexora-0.0.1.dist-info/WHEEL +5 -0
- plexora-0.0.1.dist-info/entry_points.txt +12 -0
- plexora-0.0.1.dist-info/licenses/LICENSE +207 -0
- plexora-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FigureViewOptions - rulers, grid, margins, snapping and the unit.
|
|
3
|
+
*
|
|
4
|
+
* Everything under the View menu, and nothing else. It is one file because it
|
|
5
|
+
* is one idea: these are all statements about how the page is DRAWN for this
|
|
6
|
+
* person on this machine, none of them touches the figure, and none of them
|
|
7
|
+
* belongs in the document -- two people opening the same figure should not
|
|
8
|
+
* inherit each other's rulers.
|
|
9
|
+
*
|
|
10
|
+
* So they live in localStorage, which also settles what happens on a new
|
|
11
|
+
* machine: the defaults below, which are the ones that get out of the way.
|
|
12
|
+
* Rulers and the grid are off, margins and smart guides are on, because the
|
|
13
|
+
* first two are reference and the second two are what stops a figure being
|
|
14
|
+
* subtly misaligned.
|
|
15
|
+
*
|
|
16
|
+
* ## Why the grid is a page child and the rulers are not
|
|
17
|
+
*
|
|
18
|
+
* The grid and the margins are drawn inside `.fb-page`, so they scale with it
|
|
19
|
+
* and a 5 mm square stays 5 mm at every zoom. The rulers cannot be: they are
|
|
20
|
+
* fixed to the viewport and have to redraw on scroll as well as on zoom, which
|
|
21
|
+
* is why they are `<canvas>` -- an A4 page at 1 mm resolution is 210 ticks, and
|
|
22
|
+
* 210 positioned elements rebuilt on every scroll event is a page that stutters.
|
|
23
|
+
*/
|
|
24
|
+
class FigureViewOptions {
|
|
25
|
+
|
|
26
|
+
static get STORAGE_KEY() { return "plexora.figure_builder.view"; }
|
|
27
|
+
|
|
28
|
+
/** Height of the horizontal ruler and width of the vertical one, in CSS px. */
|
|
29
|
+
static get RULER_SIZE() { return 20; }
|
|
30
|
+
|
|
31
|
+
static get DEFAULTS() {
|
|
32
|
+
return {
|
|
33
|
+
rulers: false,
|
|
34
|
+
grid: false,
|
|
35
|
+
snapGrid: false,
|
|
36
|
+
smartGuides: true,
|
|
37
|
+
margins: true,
|
|
38
|
+
units: "mm",
|
|
39
|
+
gridMm: 5,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** How many of the figure's millimetres one unit is, and how it is written. */
|
|
44
|
+
static get UNITS() {
|
|
45
|
+
return {
|
|
46
|
+
mm: { per: 1, label: "mm", step: 10, minor: 5 },
|
|
47
|
+
in: { per: 25.4, label: "in", step: 1, minor: 0.25 },
|
|
48
|
+
pt: { per: 25.4 / 72, label: "pt", step: 72, minor: 18 },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
constructor(options) {
|
|
53
|
+
this.workspace = options.workspace;
|
|
54
|
+
this.canvas = options.canvas;
|
|
55
|
+
this.prefs = { ...FigureViewOptions.DEFAULTS, ...this.read() };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
read() {
|
|
59
|
+
try {
|
|
60
|
+
return JSON.parse(window.localStorage.getItem(FigureViewOptions.STORAGE_KEY)) || {};
|
|
61
|
+
} catch (error) {
|
|
62
|
+
// Private-browsing modes throw rather than returning null. Losing a
|
|
63
|
+
// preference is a small inconvenience; throwing here would take the
|
|
64
|
+
// whole workspace down with it.
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
write() {
|
|
70
|
+
try {
|
|
71
|
+
window.localStorage.setItem(
|
|
72
|
+
FigureViewOptions.STORAGE_KEY, JSON.stringify(this.prefs));
|
|
73
|
+
} catch (error) {
|
|
74
|
+
/* see read() */
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setup() {
|
|
79
|
+
this._onScroll = () => this.drawRulers();
|
|
80
|
+
this.workspace.el("fb_canvas_scroll")
|
|
81
|
+
?.addEventListener("scroll", this._onScroll, { passive: true });
|
|
82
|
+
this._onResize = () => this.apply();
|
|
83
|
+
window.addEventListener("resize", this._onResize);
|
|
84
|
+
this.apply();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
destroy() {
|
|
88
|
+
this.workspace.el("fb_canvas_scroll")
|
|
89
|
+
?.removeEventListener("scroll", this._onScroll);
|
|
90
|
+
window.removeEventListener("resize", this._onResize);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// -- the menu ------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
menuEntries() {
|
|
96
|
+
const unit = FigureViewOptions.UNITS[this.prefs.units];
|
|
97
|
+
return [
|
|
98
|
+
{ act: "rulers", label: "Rulers", checked: this.prefs.rulers },
|
|
99
|
+
{ act: "grid", label: "Grid", checked: this.prefs.grid },
|
|
100
|
+
{ act: "snapGrid", label: "Snap to grid", checked: this.prefs.snapGrid },
|
|
101
|
+
{ act: "smartGuides", label: "Smart guides", checked: this.prefs.smartGuides },
|
|
102
|
+
{ act: "margins", label: "Show margins", checked: this.prefs.margins },
|
|
103
|
+
{ separator: true },
|
|
104
|
+
{ act: "units", label: `Units: ${unit.label}` },
|
|
105
|
+
{ separator: true },
|
|
106
|
+
{ act: "background", label: "Page background…" },
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
pick(act) {
|
|
111
|
+
if (act === "units") {
|
|
112
|
+
// Cycled rather than given a submenu: there are three, and a menu
|
|
113
|
+
// whose only job is to hold three items is a second click for no
|
|
114
|
+
// information.
|
|
115
|
+
const order = Object.keys(FigureViewOptions.UNITS);
|
|
116
|
+
this.prefs.units = order[(order.indexOf(this.prefs.units) + 1) % order.length];
|
|
117
|
+
} else if (act === "background") {
|
|
118
|
+
this.workspace.openPageBackground();
|
|
119
|
+
return;
|
|
120
|
+
} else if (act in this.prefs) {
|
|
121
|
+
this.prefs[act] = !this.prefs[act];
|
|
122
|
+
} else {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
this.write();
|
|
126
|
+
this.apply();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Set the unit outright.
|
|
131
|
+
*
|
|
132
|
+
* For a control that NAMES the three rather than cycling them -- the
|
|
133
|
+
* Transform popover has room for a select, and a field whose unit changes
|
|
134
|
+
* only by repeated clicking somewhere else is a field you cannot set.
|
|
135
|
+
* Same preference, same storage: there is one answer to "what is this page
|
|
136
|
+
* measured in", and the rulers and this popover both read it.
|
|
137
|
+
*/
|
|
138
|
+
setUnit(name) {
|
|
139
|
+
if (!(name in FigureViewOptions.UNITS) || name === this.prefs.units) return;
|
|
140
|
+
this.prefs.units = name;
|
|
141
|
+
this.write();
|
|
142
|
+
this.apply();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// -- drawing ---------------------------------------------------------------
|
|
146
|
+
|
|
147
|
+
/** Push the preferences at everything that renders from them. */
|
|
148
|
+
apply() {
|
|
149
|
+
const main = this.workspace.el("fb_main");
|
|
150
|
+
main?.classList.toggle("has-rulers", this.prefs.rulers);
|
|
151
|
+
|
|
152
|
+
this.canvas.snapping = {
|
|
153
|
+
guides: this.prefs.smartGuides,
|
|
154
|
+
grid: this.prefs.snapGrid,
|
|
155
|
+
gridMm: this.prefs.gridMm,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
this.drawGrid();
|
|
159
|
+
this.drawMargins();
|
|
160
|
+
this.drawRulers();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The grid, as a repeating gradient rather than as lines.
|
|
165
|
+
*
|
|
166
|
+
* One element and one paint, whatever the page size. Drawing it as elements
|
|
167
|
+
* would be four hundred divs on an A4 page at 5 mm, all of them rebuilt on
|
|
168
|
+
* every zoom.
|
|
169
|
+
*/
|
|
170
|
+
drawGrid() {
|
|
171
|
+
const grid = this.workspace.el("fb_page_grid");
|
|
172
|
+
if (!grid) return;
|
|
173
|
+
grid.hidden = !this.prefs.grid;
|
|
174
|
+
if (!this.prefs.grid) return;
|
|
175
|
+
const step = this.canvas.toPx(this.prefs.gridMm);
|
|
176
|
+
grid.style.backgroundSize = `${step}px ${step}px`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
drawMargins() {
|
|
180
|
+
const element = this.workspace.el("fb_page_margins");
|
|
181
|
+
const page = this.canvas.page;
|
|
182
|
+
if (!element) return;
|
|
183
|
+
element.hidden = !this.prefs.margins || !page;
|
|
184
|
+
if (element.hidden) return;
|
|
185
|
+
const margins = page.margins_mm;
|
|
186
|
+
element.style.left = this.canvas.toPx(margins.left) + "px";
|
|
187
|
+
element.style.top = this.canvas.toPx(margins.top) + "px";
|
|
188
|
+
element.style.right = this.canvas.toPx(margins.right) + "px";
|
|
189
|
+
element.style.bottom = this.canvas.toPx(margins.bottom) + "px";
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Both rulers, from where the page actually is on screen.
|
|
194
|
+
*
|
|
195
|
+
* Measured rather than computed from the scroll offset: the page is centred
|
|
196
|
+
* with `margin: auto` when it is narrower than the viewport, so its left
|
|
197
|
+
* edge is not a function of scrollLeft alone. Measuring is exact at every
|
|
198
|
+
* zoom and costs one layout read.
|
|
199
|
+
*/
|
|
200
|
+
drawRulers() {
|
|
201
|
+
if (!this.prefs.rulers) return;
|
|
202
|
+
const scroll = this.workspace.el("fb_canvas_scroll");
|
|
203
|
+
const pageEl = this.workspace.el("fb_page");
|
|
204
|
+
const page = this.canvas.page;
|
|
205
|
+
if (!scroll || !pageEl || !page) return;
|
|
206
|
+
|
|
207
|
+
const view = scroll.getBoundingClientRect();
|
|
208
|
+
const paper = pageEl.getBoundingClientRect();
|
|
209
|
+
this.paintRuler(this.workspace.el("fb_ruler_h"), "h",
|
|
210
|
+
paper.left - view.left, view.width, page.size_mm.w);
|
|
211
|
+
this.paintRuler(this.workspace.el("fb_ruler_v"), "v",
|
|
212
|
+
paper.top - view.top, view.height, page.size_mm.h);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
paintRuler(element, axis, originPx, lengthPx, spanMm) {
|
|
216
|
+
if (!element) return;
|
|
217
|
+
const dpr = window.devicePixelRatio || 1;
|
|
218
|
+
const thickness = FigureViewOptions.RULER_SIZE;
|
|
219
|
+
const width = axis === "h" ? lengthPx : thickness;
|
|
220
|
+
const height = axis === "h" ? thickness : lengthPx;
|
|
221
|
+
element.width = Math.max(1, Math.round(width * dpr));
|
|
222
|
+
element.height = Math.max(1, Math.round(height * dpr));
|
|
223
|
+
element.style.width = width + "px";
|
|
224
|
+
element.style.height = height + "px";
|
|
225
|
+
|
|
226
|
+
const context = element.getContext("2d");
|
|
227
|
+
if (!context) return;
|
|
228
|
+
context.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
229
|
+
context.clearRect(0, 0, width, height);
|
|
230
|
+
// Ink on a white strip. These were white when the workspace was dark;
|
|
231
|
+
// a canvas draws with literal colours and knows nothing about the
|
|
232
|
+
// stylesheet, so the theme change has to be made here by hand.
|
|
233
|
+
context.fillStyle = "rgba(22, 32, 46, 0.62)";
|
|
234
|
+
context.strokeStyle = "rgba(22, 32, 46, 0.38)";
|
|
235
|
+
context.font = "9px system-ui, sans-serif";
|
|
236
|
+
context.lineWidth = 1;
|
|
237
|
+
|
|
238
|
+
const unit = FigureViewOptions.UNITS[this.prefs.units];
|
|
239
|
+
const perUnitPx = this.canvas.toPx(unit.per);
|
|
240
|
+
// Skip labels that would overlap: at 25% zoom every 10 mm is four
|
|
241
|
+
// pixels apart, and a ruler of overlapping numbers is worse than none.
|
|
242
|
+
const labelEvery = Math.max(unit.step, unit.step * Math.ceil(28 / (perUnitPx * unit.step)));
|
|
243
|
+
const minorEvery = perUnitPx * unit.minor >= 4 ? unit.minor : labelEvery;
|
|
244
|
+
|
|
245
|
+
const spanUnits = spanMm / unit.per;
|
|
246
|
+
for (let value = 0; value <= spanUnits + 1e-6; value += minorEvery) {
|
|
247
|
+
const at = originPx + value * perUnitPx;
|
|
248
|
+
if (at < -20 || at > lengthPx + 20) continue;
|
|
249
|
+
const major = Math.abs(value % labelEvery) < 1e-6;
|
|
250
|
+
const tick = major ? thickness * 0.6 : thickness * 0.3;
|
|
251
|
+
context.beginPath();
|
|
252
|
+
if (axis === "h") {
|
|
253
|
+
context.moveTo(Math.round(at) + 0.5, thickness - tick);
|
|
254
|
+
context.lineTo(Math.round(at) + 0.5, thickness);
|
|
255
|
+
} else {
|
|
256
|
+
context.moveTo(thickness - tick, Math.round(at) + 0.5);
|
|
257
|
+
context.lineTo(thickness, Math.round(at) + 0.5);
|
|
258
|
+
}
|
|
259
|
+
context.stroke();
|
|
260
|
+
if (!major) continue;
|
|
261
|
+
const text = String(Math.round(value * 100) / 100);
|
|
262
|
+
if (axis === "h") {
|
|
263
|
+
context.fillText(text, at + 2, 9);
|
|
264
|
+
} else {
|
|
265
|
+
context.save();
|
|
266
|
+
context.translate(9, at - 2);
|
|
267
|
+
context.rotate(-Math.PI / 2);
|
|
268
|
+
context.fillText(text, 0, 0);
|
|
269
|
+
context.restore();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|