cloudmr-ux 4.4.8 → 4.5.0
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.
- package/dist/CmrComponents/niivue-viewer/CloudMrNiivuePanel.d.ts +12 -2
- package/dist/CmrComponents/niivue-viewer/CloudMrNiivuePanel.js +4 -0
- package/dist/CmrComponents/niivue-viewer/CloudMrNiivueViewer.js +86 -25
- package/dist/CmrComponents/niivue-viewer/NiivuePatcher.js +58 -0
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/BrushSizeSlider.d.ts +5 -0
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/BrushSizeSlider.js +36 -0
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/DrawColorPlatte.d.ts +10 -1
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/DrawColorPlatte.js +39 -6
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/EraserPlatte.d.ts +7 -2
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/EraserPlatte.js +20 -36
- package/dist/CmrComponents/niivue-viewer/mro-draw-toolkit/MroDrawToolkit.js +1 -1
- package/dist/CmrComponents/niivue-viewer/polylinePenUtils.d.ts +12 -0
- package/dist/CmrComponents/niivue-viewer/polylinePenUtils.js +123 -0
- package/package.json +1 -1
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import "./Toolbar.css";
|
|
3
3
|
import type { DrawToolkitProps } from "../draw-toolkit/DrawToolkit";
|
|
4
|
-
/** Props for {@link
|
|
5
|
-
export type CloudMrDrawToolkitProps = Omit<DrawToolkitProps, "
|
|
4
|
+
/** Props for {@link MroDrawToolkit} — extends draw toolkit with MRO pen/shape controls. */
|
|
5
|
+
export type CloudMrDrawToolkitProps = Omit<DrawToolkitProps, "rois" | "selectedROI" | "setSelectedROI" | "saveROI" | "labelsVisible" | "toggleLabelsVisible"> & {
|
|
6
|
+
penDrawMode?: "freehand" | "polyline";
|
|
7
|
+
onPenDrawModeChange?: (mode: "freehand" | "polyline") => void;
|
|
8
|
+
polylineVertexCount?: number;
|
|
9
|
+
onCancelPolyline?: () => void;
|
|
10
|
+
onFinishPolyline?: () => void;
|
|
11
|
+
onCloseFillPolyline?: () => void;
|
|
12
|
+
shapeDraftActive?: boolean;
|
|
13
|
+
onApplyShapeDraft?: () => void;
|
|
14
|
+
onCancelShapeDraft?: () => void;
|
|
15
|
+
};
|
|
6
16
|
export interface CloudMrNiivuePanelProps {
|
|
7
17
|
nv: any;
|
|
8
18
|
pipelineID: string;
|
|
@@ -106,9 +106,13 @@ export function CloudMrNiivuePanel(props) {
|
|
|
106
106
|
props.resampleImage();
|
|
107
107
|
}, [histogram]);
|
|
108
108
|
function applyDrawShapeTool(tool) {
|
|
109
|
+
var _a, _b;
|
|
109
110
|
if (props.shapeDraft) {
|
|
110
111
|
props.onCancelShapeDraft();
|
|
111
112
|
}
|
|
113
|
+
if (tool !== "pen") {
|
|
114
|
+
(_b = (_a = props.drawToolkitProps).onPenDrawModeChange) === null || _b === void 0 ? void 0 : _b.call(_a, "freehand");
|
|
115
|
+
}
|
|
112
116
|
props.setDrawShapeTool(tool);
|
|
113
117
|
var nv = props.nv;
|
|
114
118
|
nv.opts.deferShapeCommit = tool === "rectangle" || tool === "ellipse";
|
|
@@ -108,6 +108,7 @@ export var nv = new Niivue({
|
|
|
108
108
|
penType: NI_PEN_TYPE.PEN
|
|
109
109
|
});
|
|
110
110
|
nv.opts.penBounds = 0;
|
|
111
|
+
nv.opts.penSize = 1;
|
|
111
112
|
window.nv = nv;
|
|
112
113
|
// The NiiVue component wraps all other components in the UI.
|
|
113
114
|
// It is exported so that it can be used in other projects easily
|
|
@@ -169,15 +170,19 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
169
170
|
var _21 = useState(false), saving = _21[0], setSaving = _21[1];
|
|
170
171
|
var _22 = useState(null), drawShapeTool = _22[0], setDrawShapeTool = _22[1];
|
|
171
172
|
var _23 = useState(null), shapeDraft = _23[0], setShapeDraft = _23[1];
|
|
173
|
+
var _24 = useState("freehand"), penDrawMode = _24[0], setPenDrawMode = _24[1];
|
|
174
|
+
var _25 = useState(0), polylineVertexCount = _25[0], setPolylineVertexCount = _25[1];
|
|
175
|
+
var _26 = useState(1), brushSize = _26[0], setBrushSize = _26[1];
|
|
172
176
|
var shapeDraftRef = React.useRef(null);
|
|
173
177
|
var drawShapeToolRef = React.useRef(null);
|
|
174
178
|
drawShapeToolRef.current = drawShapeTool;
|
|
175
179
|
shapeDraftRef.current = shapeDraft;
|
|
176
180
|
React.useEffect(function () {
|
|
177
181
|
nv.opts.penBounds = 0;
|
|
182
|
+
nv.opts.penSize = 1;
|
|
178
183
|
}, []);
|
|
179
|
-
var
|
|
180
|
-
var
|
|
184
|
+
var _27 = React.useState(1.0), gamma = _27[0], setGamma = _27[1];
|
|
185
|
+
var _28 = React.useState(0), gammaKey = _28[0], setGammaKey = _28[1];
|
|
181
186
|
// Niivue → React bridge so other places (Toolbar) can force the UI to reset
|
|
182
187
|
nv.onResetGamma = function () {
|
|
183
188
|
setGamma(1.0);
|
|
@@ -222,13 +227,13 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
222
227
|
// setLayers([...nv.volumes])
|
|
223
228
|
// }, [])
|
|
224
229
|
// values dualslider
|
|
225
|
-
var
|
|
230
|
+
var _29 = useState(0), rangeKey = _29[0], setRangeKey = _29[1];
|
|
226
231
|
nv.onResetContrast = function () {
|
|
227
232
|
setRangeKey(rangeKey + 1);
|
|
228
233
|
};
|
|
229
|
-
var
|
|
230
|
-
var
|
|
231
|
-
var
|
|
234
|
+
var _30 = useState([0, 0, 0]), boundMins = _30[0], setBoundMins = _30[1];
|
|
235
|
+
var _31 = useState([1, 1, 1]), boundMaxs = _31[0], setBoundMaxs = _31[1];
|
|
236
|
+
var _32 = useState([0.5, 0.5, 0.5]), mms = _32[0], setMMs = _32[1];
|
|
232
237
|
nv.onImageLoaded = function () {
|
|
233
238
|
var _a, _b;
|
|
234
239
|
var oldCrosshairPos = __spreadArray([], nv.scene.crosshairPos, true);
|
|
@@ -511,7 +516,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
511
516
|
setTextsVisible(true);
|
|
512
517
|
}
|
|
513
518
|
}
|
|
514
|
-
var
|
|
519
|
+
var _33 = useState("pan"), dragMode = _33[0], setDragMode = _33[1];
|
|
515
520
|
function nvSetDragMode(dragMode) {
|
|
516
521
|
switch (dragMode) {
|
|
517
522
|
case "none":
|
|
@@ -548,11 +553,15 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
548
553
|
nv.setDrawingEnabled(enabled);
|
|
549
554
|
nv.drawScene();
|
|
550
555
|
}
|
|
556
|
+
function nvUpdateBrushSize(size) {
|
|
557
|
+
setBrushSize(size);
|
|
558
|
+
nv.opts.penBounds = (size - 1) / 2;
|
|
559
|
+
nv.opts.penSize = size;
|
|
560
|
+
}
|
|
551
561
|
function nvUpdateDrawPen(a) {
|
|
552
562
|
var raw = Number(a.target.value);
|
|
553
563
|
setDrawPen(raw);
|
|
554
564
|
var penValue = raw;
|
|
555
|
-
nv.opts.penBounds = 0;
|
|
556
565
|
nv.setPenValue(penValue & 7, penValue > 0);
|
|
557
566
|
if (penValue == 8) {
|
|
558
567
|
nv.setPenValue(0, true);
|
|
@@ -720,7 +729,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
720
729
|
nv.opts.crosshairWidth = w;
|
|
721
730
|
nv.drawScene();
|
|
722
731
|
}
|
|
723
|
-
var
|
|
732
|
+
var _34 = useState({}), labelMapping = _34[0], setLabelMapping = _34[1];
|
|
724
733
|
function resampleImage(mapping) {
|
|
725
734
|
if (mapping === void 0) { mapping = labelMapping; }
|
|
726
735
|
var el = typeof document !== "undefined" ? document.getElementById("histoplot") : null;
|
|
@@ -733,6 +742,34 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
733
742
|
setROIs(next);
|
|
734
743
|
}
|
|
735
744
|
}
|
|
745
|
+
function syncPenDrawMode(mode) {
|
|
746
|
+
var _a;
|
|
747
|
+
setPenDrawMode(mode);
|
|
748
|
+
nv.opts.polylinePenMode = mode === "polyline";
|
|
749
|
+
nv.opts.isFilledPen = mode === "freehand";
|
|
750
|
+
if (mode === "freehand") {
|
|
751
|
+
(_a = nv.cloudMrCancelPolyline) === null || _a === void 0 ? void 0 : _a.call(nv);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
function cancelPolylineDraft() {
|
|
755
|
+
var _a;
|
|
756
|
+
(_a = nv.cloudMrCancelPolyline) === null || _a === void 0 ? void 0 : _a.call(nv);
|
|
757
|
+
}
|
|
758
|
+
function finishPolylineOpen() {
|
|
759
|
+
if (nv.cloudMrFinishPolyline(false)) {
|
|
760
|
+
setDrawingChanged(true);
|
|
761
|
+
resampleImage();
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
function finishPolylineClosed() {
|
|
765
|
+
if (nv.cloudMrFinishPolyline(true)) {
|
|
766
|
+
setDrawingChanged(true);
|
|
767
|
+
resampleImage();
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
nv.onPolylineChange = function (count) {
|
|
771
|
+
setPolylineVertexCount(count);
|
|
772
|
+
};
|
|
736
773
|
function cancelShapeDraft() {
|
|
737
774
|
var draft = shapeDraftRef.current;
|
|
738
775
|
if (!draft)
|
|
@@ -771,26 +808,38 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
771
808
|
nvSetDrawingEnabled(false);
|
|
772
809
|
};
|
|
773
810
|
React.useEffect(function () {
|
|
774
|
-
if (!shapeDraft)
|
|
811
|
+
if (!shapeDraft && !(penDrawMode === "polyline" && polylineVertexCount >= 2)) {
|
|
775
812
|
return undefined;
|
|
813
|
+
}
|
|
776
814
|
var onKeyDown = function (event) {
|
|
777
|
-
if (event.key === "
|
|
815
|
+
if (event.key === "Escape") {
|
|
778
816
|
event.preventDefault();
|
|
779
|
-
|
|
817
|
+
if (shapeDraft) {
|
|
818
|
+
cancelShapeDraft();
|
|
819
|
+
}
|
|
820
|
+
else if (polylineVertexCount >= 2) {
|
|
821
|
+
cancelPolylineDraft();
|
|
822
|
+
}
|
|
823
|
+
return;
|
|
780
824
|
}
|
|
781
|
-
|
|
825
|
+
if (event.key === "Enter") {
|
|
782
826
|
event.preventDefault();
|
|
783
|
-
|
|
827
|
+
if (shapeDraft) {
|
|
828
|
+
applyShapeDraft();
|
|
829
|
+
}
|
|
830
|
+
else if (penDrawMode === "polyline" && polylineVertexCount >= 2) {
|
|
831
|
+
finishPolylineOpen();
|
|
832
|
+
}
|
|
784
833
|
}
|
|
785
834
|
};
|
|
786
835
|
window.addEventListener("keydown", onKeyDown);
|
|
787
836
|
return function () { return window.removeEventListener("keydown", onKeyDown); };
|
|
788
|
-
}, [shapeDraft]);
|
|
837
|
+
}, [shapeDraft, penDrawMode, polylineVertexCount]);
|
|
789
838
|
function nvUpdateSelectionBoxColor(rgb01) {
|
|
790
839
|
setSelectionBoxColor(__spreadArray(__spreadArray([], rgb01, true), [0.5], false));
|
|
791
840
|
nv.setSelectionBoxColor(__spreadArray(__spreadArray([], rgb01, true), [0.5], false));
|
|
792
841
|
}
|
|
793
|
-
var
|
|
842
|
+
var _35 = React.useState('axial'), sliceType = _35[0], setSliceType = _35[1];
|
|
794
843
|
function nvUpdateSliceType(newSliceType) {
|
|
795
844
|
setSliceType(newSliceType);
|
|
796
845
|
if (newSliceType === 'axial') {
|
|
@@ -930,14 +979,14 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
930
979
|
return [2 /*return*/];
|
|
931
980
|
});
|
|
932
981
|
}); };
|
|
933
|
-
var
|
|
934
|
-
var
|
|
935
|
-
var
|
|
936
|
-
}), saveConfirmCallback =
|
|
937
|
-
var
|
|
938
|
-
var
|
|
939
|
-
var
|
|
940
|
-
var
|
|
982
|
+
var _36 = useState(''), selectedROI = _36[0], setSelectedDrawingLayer = _36[1];
|
|
983
|
+
var _37 = useState(false), saveDialogOpen = _37[0], setSaveDialogOpen = _37[1];
|
|
984
|
+
var _38 = useState(function () {
|
|
985
|
+
}), saveConfirmCallback = _38[0], setSaveConfirmCallback = _38[1];
|
|
986
|
+
var _39 = useState(false), confirmationOpen = _39[0], setConfirmationOpen = _39[1];
|
|
987
|
+
var _40 = useState(function () { }), warningConfirmationCallback = _40[0], setWarningConfirmationCallback = _40[1];
|
|
988
|
+
var _41 = useState(function () { }), warningCancelCallback = _41[0], setWarningCancelCallback = _41[1];
|
|
989
|
+
var _42 = useState(false), drawingChanged = _42[0], setDrawingChanged = _42[1];
|
|
941
990
|
// When new drawing strokes are made on top of a saved ROI, reset the dropdown
|
|
942
991
|
// so it shows the "ROI Layer" placeholder instead of the stale saved name.
|
|
943
992
|
React.useEffect(function () {
|
|
@@ -1264,6 +1313,10 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
1264
1313
|
cancelShapeDraft();
|
|
1265
1314
|
return;
|
|
1266
1315
|
}
|
|
1316
|
+
if (polylineVertexCount > 0) {
|
|
1317
|
+
cancelPolylineDraft();
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1267
1320
|
nv.drawUndo();
|
|
1268
1321
|
resampleImage();
|
|
1269
1322
|
if (nv.drawBitmap && nv.drawBitmap.every(function (v) { return v === 0; })) {
|
|
@@ -1275,7 +1328,15 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
1275
1328
|
toggleROIVisible: toggleROIVisible,
|
|
1276
1329
|
drawingOpacity: drawingOpacity,
|
|
1277
1330
|
setDrawingOpacity: nvUpdateDrawingOpacity,
|
|
1278
|
-
setDrawingChanged: setDrawingChanged
|
|
1331
|
+
setDrawingChanged: setDrawingChanged,
|
|
1332
|
+
penDrawMode: penDrawMode,
|
|
1333
|
+
onPenDrawModeChange: syncPenDrawMode,
|
|
1334
|
+
polylineVertexCount: polylineVertexCount,
|
|
1335
|
+
onCancelPolyline: cancelPolylineDraft,
|
|
1336
|
+
onFinishPolyline: finishPolylineOpen,
|
|
1337
|
+
onCloseFillPolyline: finishPolylineClosed,
|
|
1338
|
+
brushSize: brushSize,
|
|
1339
|
+
updateBrushSize: nvUpdateBrushSize
|
|
1279
1340
|
};
|
|
1280
1341
|
return (_jsxs(Box, __assign({ sx: {
|
|
1281
1342
|
display: 'flex',
|
|
@@ -7,6 +7,15 @@ import {
|
|
|
7
7
|
isDraftTooSmall,
|
|
8
8
|
shouldDeferShapeCommit,
|
|
9
9
|
} from "./shapeDraftUtils.js";
|
|
10
|
+
import {
|
|
11
|
+
addPolylineVertex,
|
|
12
|
+
cancelPolyline,
|
|
13
|
+
finishPolyline,
|
|
14
|
+
isClickWithoutDrag,
|
|
15
|
+
isPolylinePenActive,
|
|
16
|
+
previewPolylineSegment,
|
|
17
|
+
resetPolylineState,
|
|
18
|
+
} from "./polylinePenUtils.js";
|
|
10
19
|
|
|
11
20
|
/*
|
|
12
21
|
* bitmapOverlay — in-browser state only: remembers each voxel's label *before* Group
|
|
@@ -1414,14 +1423,63 @@ Niivue.prototype.drawAddUndoBitmap = function cloudMrDrawAddUndoBitmap(...args)
|
|
|
1414
1423
|
return _drawAddUndoBitmap.apply(this, args);
|
|
1415
1424
|
};
|
|
1416
1425
|
|
|
1426
|
+
Niivue.prototype.cloudMrCancelPolyline = function cloudMrCancelPolyline() {
|
|
1427
|
+
cancelPolyline(this);
|
|
1428
|
+
};
|
|
1429
|
+
|
|
1430
|
+
Niivue.prototype.cloudMrFinishPolyline = function cloudMrFinishPolyline(fillClosed = false) {
|
|
1431
|
+
return finishPolyline(this, { fillClosed });
|
|
1432
|
+
};
|
|
1433
|
+
|
|
1434
|
+
Niivue.prototype.cloudMrResetPolyline = function cloudMrResetPolyline() {
|
|
1435
|
+
resetPolylineState(this);
|
|
1436
|
+
};
|
|
1437
|
+
|
|
1438
|
+
const _mouseClick = Niivue.prototype.mouseClick;
|
|
1439
|
+
Niivue.prototype.mouseClick = function cloudMrMouseClick(...args) {
|
|
1440
|
+
if (isPolylinePenActive(this)) {
|
|
1441
|
+
if (this._cloudMrPolylineVertices?.length > 0) {
|
|
1442
|
+
previewPolylineSegment(this);
|
|
1443
|
+
}
|
|
1444
|
+
return false;
|
|
1445
|
+
}
|
|
1446
|
+
return _mouseClick.apply(this, args);
|
|
1447
|
+
};
|
|
1448
|
+
|
|
1449
|
+
const _mouseMoveListener = Niivue.prototype.mouseMoveListener;
|
|
1450
|
+
Niivue.prototype.mouseMoveListener = function cloudMrMouseMoveListener(event) {
|
|
1451
|
+
const result = _mouseMoveListener.call(this, event);
|
|
1452
|
+
if (isPolylinePenActive(this) && this._cloudMrPolylineVertices?.length > 0) {
|
|
1453
|
+
previewPolylineSegment(this);
|
|
1454
|
+
}
|
|
1455
|
+
return result;
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1417
1458
|
const _mouseUpListener = Niivue.prototype.mouseUpListener;
|
|
1418
1459
|
Niivue.prototype.mouseUpListener = function cloudMrMouseUpListener() {
|
|
1419
1460
|
let pendingDraft = null;
|
|
1461
|
+
let polylineClick = false;
|
|
1462
|
+
|
|
1420
1463
|
if (shouldDeferShapeCommit(this)) {
|
|
1421
1464
|
this._cloudMrSkipNextUndoBitmap = true;
|
|
1422
1465
|
pendingDraft = captureDeferredShapeDraft(this);
|
|
1423
1466
|
}
|
|
1467
|
+
|
|
1468
|
+
if (isPolylinePenActive(this) && isClickWithoutDrag(this.uiData)) {
|
|
1469
|
+
this.drawPenLocation = [NaN, NaN, NaN];
|
|
1470
|
+
this.drawPenFillPts = [];
|
|
1471
|
+
this._cloudMrSkipNextUndoBitmap = true;
|
|
1472
|
+
this._cloudMrSuppressDrawingChangedMouseUp = true;
|
|
1473
|
+
polylineClick = true;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1424
1476
|
_mouseUpListener.call(this);
|
|
1477
|
+
|
|
1478
|
+
if (polylineClick) {
|
|
1479
|
+
addPolylineVertex(this);
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1425
1483
|
if (!pendingDraft?.baseBitmap) {
|
|
1426
1484
|
return;
|
|
1427
1485
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
+
import { Stack, Slider, Typography } from "@mui/material";
|
|
14
|
+
var SLIDER_SX = {
|
|
15
|
+
width: "80%",
|
|
16
|
+
color: "#fff",
|
|
17
|
+
"& .MuiSlider-track": { backgroundColor: "#fff", border: "none" },
|
|
18
|
+
"& .MuiSlider-rail": { backgroundColor: "rgba(255,255,255,0.3)" },
|
|
19
|
+
"& .MuiSlider-thumb": {
|
|
20
|
+
backgroundColor: "#fff",
|
|
21
|
+
border: "2px solid #fff",
|
|
22
|
+
"&:hover, &.Mui-focusVisible, &.Mui-active": {
|
|
23
|
+
boxShadow: "0 0 0 8px rgba(255,255,255,0.16)"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"& .MuiSlider-mark": { backgroundColor: "#fff" },
|
|
27
|
+
"& .MuiSlider-markActive": { backgroundColor: "#fff" },
|
|
28
|
+
"& .MuiSlider-valueLabel": {
|
|
29
|
+
backgroundColor: "#fff",
|
|
30
|
+
color: "#000"
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
export function BrushSizeSlider(_a) {
|
|
34
|
+
var label = _a.label, brushSize = _a.brushSize, updateBrushSize = _a.updateBrushSize;
|
|
35
|
+
return (_jsxs(Stack, __assign({ sx: { mb: 0.5, px: 0.5 }, alignItems: "center", width: "100%" }, { children: [_jsxs(Typography, __assign({ color: "white", noWrap: true, width: "100%", marginLeft: "6pt", fontSize: "11pt", sx: { userSelect: "none" } }, { children: [label, ": ", brushSize] })), _jsx(Slider, { value: brushSize, sx: SLIDER_SX, step: 2, min: 1, max: 15, marks: true, onChange: function (_event, value) { return updateBrushSize(value); } })] })));
|
|
36
|
+
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
export default function DrawColorPlatte({ expanded, updateDrawPen, setDrawingEnabled, shapeDraftActive, onApplyShapeDraft, onCancelShapeDraft, }: {
|
|
1
|
+
export default function DrawColorPlatte({ expanded, updateDrawPen, setDrawingEnabled, showPenModes, penDrawMode, onPenDrawModeChange, polylineVertexCount, onCancelPolyline, onFinishPolyline, onCloseFillPolyline, brushSize, updateBrushSize, shapeDraftActive, onApplyShapeDraft, onCancelShapeDraft, }: {
|
|
2
2
|
expanded: any;
|
|
3
3
|
updateDrawPen: any;
|
|
4
4
|
setDrawingEnabled: any;
|
|
5
|
+
showPenModes?: boolean | undefined;
|
|
6
|
+
penDrawMode?: string | undefined;
|
|
7
|
+
onPenDrawModeChange: any;
|
|
8
|
+
polylineVertexCount?: number | undefined;
|
|
9
|
+
onCancelPolyline: any;
|
|
10
|
+
onFinishPolyline: any;
|
|
11
|
+
onCloseFillPolyline: any;
|
|
12
|
+
brushSize?: number | undefined;
|
|
13
|
+
updateBrushSize: any;
|
|
5
14
|
shapeDraftActive?: boolean | undefined;
|
|
6
15
|
onApplyShapeDraft: any;
|
|
7
16
|
onCancelShapeDraft: any;
|
|
@@ -12,12 +12,13 @@ var __assign = (this && this.__assign) || function () {
|
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
/**
|
|
14
14
|
* Shared ROI label color row (NiiVue pen indices 1–6). Used by pen, rectangle, and ellipse tools.
|
|
15
|
-
*
|
|
15
|
+
* Pen palette adds freehand vs straight-line mode; rectangle/ellipse show Apply/Cancel while adjusting.
|
|
16
16
|
*/
|
|
17
|
-
import { Stack, IconButton, Button, Tooltip } from "@mui/material";
|
|
17
|
+
import { Stack, IconButton, Button, Tooltip, Typography } from "@mui/material";
|
|
18
18
|
import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord";
|
|
19
19
|
import CheckIcon from "@mui/icons-material/Check";
|
|
20
20
|
import CloseIcon from "@mui/icons-material/Close";
|
|
21
|
+
import { BrushSizeSlider } from "./BrushSizeSlider";
|
|
21
22
|
var FILLED_COLORS = [
|
|
22
23
|
{ sx: { color: "red" } },
|
|
23
24
|
{ sx: { color: "green" } },
|
|
@@ -28,24 +29,56 @@ var FILLED_COLORS = [
|
|
|
28
29
|
];
|
|
29
30
|
var ACTION_FONT_SIZE = "0.75rem";
|
|
30
31
|
var ACTION_ICON_SIZE = "0.875rem";
|
|
32
|
+
var modeBtnSx = function (active) { return ({
|
|
33
|
+
color: active ? "#c9a0e8" : "#bbb",
|
|
34
|
+
fontSize: ACTION_FONT_SIZE,
|
|
35
|
+
textTransform: "none",
|
|
36
|
+
minWidth: 0,
|
|
37
|
+
py: 0.25,
|
|
38
|
+
px: 0.75
|
|
39
|
+
}); };
|
|
31
40
|
export default function DrawColorPlatte(_a) {
|
|
32
|
-
var expanded = _a.expanded, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled, _b = _a.
|
|
41
|
+
var expanded = _a.expanded, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled, _b = _a.showPenModes, showPenModes = _b === void 0 ? false : _b, _c = _a.penDrawMode, penDrawMode = _c === void 0 ? "freehand" : _c, onPenDrawModeChange = _a.onPenDrawModeChange, _d = _a.polylineVertexCount, polylineVertexCount = _d === void 0 ? 0 : _d, onCancelPolyline = _a.onCancelPolyline, onFinishPolyline = _a.onFinishPolyline, onCloseFillPolyline = _a.onCloseFillPolyline, _e = _a.brushSize, brushSize = _e === void 0 ? 1 : _e, updateBrushSize = _a.updateBrushSize, _f = _a.shapeDraftActive, shapeDraftActive = _f === void 0 ? false : _f, onApplyShapeDraft = _a.onApplyShapeDraft, onCancelShapeDraft = _a.onCancelShapeDraft;
|
|
33
42
|
return (_jsxs(Stack, __assign({ style: {
|
|
34
43
|
position: "absolute",
|
|
35
44
|
top: "100%",
|
|
36
45
|
left: 0,
|
|
37
46
|
zIndex: 1500,
|
|
38
47
|
border: "".concat(expanded ? "1px" : 0, " solid #bbb"),
|
|
39
|
-
maxWidth: expanded ?
|
|
48
|
+
maxWidth: expanded ? 320 : 0,
|
|
49
|
+
minWidth: expanded ? 240 : 0,
|
|
40
50
|
overflow: expanded ? "visible" : "hidden",
|
|
41
51
|
borderRadius: "16px",
|
|
42
52
|
borderTopLeftRadius: "6pt",
|
|
43
53
|
borderTopRightRadius: "6pt",
|
|
44
54
|
background: "#333"
|
|
45
|
-
}, direction: "column", spacing: 0.5, sx: { py:
|
|
55
|
+
}, direction: "column", spacing: 0.5, sx: { py: expanded ? 0.5 : 0 } }, { children: [showPenModes && expanded && (_jsxs(Stack, __assign({ direction: "row", alignItems: "center", spacing: 0.5, sx: { px: 0.75, pt: 0.25 } }, { children: [_jsx(Button, __assign({ size: "small", onClick: function () { return onPenDrawModeChange === null || onPenDrawModeChange === void 0 ? void 0 : onPenDrawModeChange("freehand"); }, sx: modeBtnSx(penDrawMode === "freehand") }, { children: "Freehand" })), _jsx(Button, __assign({ size: "small", onClick: function () { return onPenDrawModeChange === null || onPenDrawModeChange === void 0 ? void 0 : onPenDrawModeChange("polyline"); }, sx: modeBtnSx(penDrawMode === "polyline") }, { children: "Straight lines" }))] }))), showPenModes && expanded && updateBrushSize && (_jsx(BrushSizeSlider, { label: "Line thickness", brushSize: brushSize, updateBrushSize: updateBrushSize })), _jsx(Stack, __assign({ direction: "row" }, { children: FILLED_COLORS.map(function (color, index) { return (_jsx(IconButton, __assign({ onClick: function () {
|
|
46
56
|
updateDrawPen({ target: { value: index + 1 } });
|
|
47
57
|
setDrawingEnabled(true);
|
|
48
|
-
} }, { children: _jsx(FiberManualRecordIcon, { sx: color.sx }) }), index)); }) })),
|
|
58
|
+
} }, { children: _jsx(FiberManualRecordIcon, { sx: color.sx }) }), index)); }) })), showPenModes && penDrawMode === "polyline" && expanded && polylineVertexCount === 0 && (_jsx(Typography, __assign({ sx: { px: 1, pb: 0.5, fontSize: "0.68rem", color: "#aaa", userSelect: "none" } }, { children: "Click each corner to draw connected straight lines" }))), showPenModes && penDrawMode === "polyline" && expanded && polylineVertexCount >= 2 && (_jsxs(Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1, py: 0.5, borderTop: "1px solid #555", width: "100%" } }, { children: [_jsx(Tooltip, __assign({ title: "Discard current outline" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "cancel polyline", onClick: function () { return onCancelPolyline === null || onCancelPolyline === void 0 ? void 0 : onCancelPolyline(); }, startIcon: _jsx(CloseIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
|
|
59
|
+
color: "#ccc",
|
|
60
|
+
fontSize: ACTION_FONT_SIZE,
|
|
61
|
+
textTransform: "none",
|
|
62
|
+
minWidth: 0,
|
|
63
|
+
py: 0.25,
|
|
64
|
+
px: 0.75,
|
|
65
|
+
"& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
|
|
66
|
+
} }, { children: "Cancel" })) })), _jsxs(Stack, __assign({ direction: "row", alignItems: "center", spacing: 1 }, { children: [polylineVertexCount >= 3 && (_jsx(Tooltip, __assign({ title: "Connect last point to first and fill" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "close and fill polyline", onClick: function () { return onCloseFillPolyline === null || onCloseFillPolyline === void 0 ? void 0 : onCloseFillPolyline(); }, sx: {
|
|
67
|
+
color: "#c9a0e8",
|
|
68
|
+
fontSize: ACTION_FONT_SIZE,
|
|
69
|
+
textTransform: "none",
|
|
70
|
+
minWidth: 0,
|
|
71
|
+
py: 0.25,
|
|
72
|
+
px: 0.75
|
|
73
|
+
} }, { children: "Close & fill" })) }))), _jsx(Tooltip, __assign({ title: "Keep outline only (Enter)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "finish polyline", onClick: function () { return onFinishPolyline === null || onFinishPolyline === void 0 ? void 0 : onFinishPolyline(); }, startIcon: _jsx(CheckIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
|
|
74
|
+
color: "#c9a0e8",
|
|
75
|
+
fontSize: ACTION_FONT_SIZE,
|
|
76
|
+
textTransform: "none",
|
|
77
|
+
minWidth: 0,
|
|
78
|
+
py: 0.25,
|
|
79
|
+
px: 0.75,
|
|
80
|
+
"& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
|
|
81
|
+
} }, { children: "Done" })) }))] }))] }))), shapeDraftActive && expanded && (_jsxs(Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1, py: 0.5, borderTop: "1px solid #555", width: "100%" } }, { children: [_jsx(Tooltip, __assign({ title: "Cancel shape (Esc)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "cancel shape", onClick: function () { return onCancelShapeDraft === null || onCancelShapeDraft === void 0 ? void 0 : onCancelShapeDraft(); }, startIcon: _jsx(CloseIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
|
|
49
82
|
color: "#ccc",
|
|
50
83
|
fontSize: ACTION_FONT_SIZE,
|
|
51
84
|
textTransform: "none",
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
export default EraserPlatte
|
|
2
|
-
|
|
1
|
+
export default function EraserPlatte({ expandEraseOptions, updateDrawPen, setDrawingEnabled, brushSize, updateBrushSize, }: {
|
|
2
|
+
expandEraseOptions: any;
|
|
3
|
+
updateDrawPen: any;
|
|
4
|
+
setDrawingEnabled: any;
|
|
5
|
+
brushSize?: number | undefined;
|
|
6
|
+
updateBrushSize: any;
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,29 +1,26 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
1
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
13
|
import { Stack, IconButton } from "@mui/material";
|
|
3
14
|
import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord";
|
|
4
15
|
import FiberManualRecordOutlinedIcon from "@mui/icons-material/FiberManualRecordOutlined";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
function (t) {
|
|
9
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
10
|
-
s = arguments[i];
|
|
11
|
-
for (var p in s)
|
|
12
|
-
if (Object.prototype.hasOwnProperty.call(s, p))
|
|
13
|
-
t[p] = s[p];
|
|
14
|
-
}
|
|
15
|
-
return t;
|
|
16
|
-
};
|
|
17
|
-
return __assign.apply(this, arguments);
|
|
18
|
-
};
|
|
19
|
-
var EraserPlatte = function (_a) {
|
|
20
|
-
var expandEraseOptions = _a.expandEraseOptions, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled;
|
|
16
|
+
import { BrushSizeSlider } from "./BrushSizeSlider";
|
|
17
|
+
export default function EraserPlatte(_a) {
|
|
18
|
+
var expandEraseOptions = _a.expandEraseOptions, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled, _b = _a.brushSize, brushSize = _b === void 0 ? 1 : _b, updateBrushSize = _a.updateBrushSize;
|
|
21
19
|
var eraseOptions = [
|
|
22
20
|
_jsx(FiberManualRecordIcon, { style: { color: "white" } }, "e0"),
|
|
23
21
|
_jsx(FiberManualRecordOutlinedIcon, { style: { color: "white" } }, "e1"),
|
|
24
22
|
];
|
|
25
|
-
return _jsxs(Stack, __assign({
|
|
26
|
-
style: {
|
|
23
|
+
return (_jsxs(Stack, __assign({ style: {
|
|
27
24
|
position: "absolute",
|
|
28
25
|
top: "100%",
|
|
29
26
|
left: 0,
|
|
@@ -36,21 +33,8 @@ var EraserPlatte = function (_a) {
|
|
|
36
33
|
borderTopRightRadius: "6pt",
|
|
37
34
|
background: "#333",
|
|
38
35
|
width: 150
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
children: eraseOptions.map(function (value, index) {
|
|
45
|
-
return _jsx(IconButton, __assign({
|
|
46
|
-
onClick: function () {
|
|
47
|
-
updateDrawPen({ target: { value: index === 0 ? 8 : 0 } });
|
|
48
|
-
setDrawingEnabled(true);
|
|
49
|
-
}
|
|
50
|
-
}, { children: value }), index);
|
|
51
|
-
})
|
|
52
|
-
})),
|
|
53
|
-
]
|
|
54
|
-
}));
|
|
55
|
-
};
|
|
56
|
-
export default EraserPlatte;
|
|
36
|
+
}, direction: "column" }, { children: [updateBrushSize && (_jsx(BrushSizeSlider, { label: "Eraser size", brushSize: brushSize, updateBrushSize: updateBrushSize })), _jsx(Stack, __assign({ direction: "row", style: { justifyContent: "center" } }, { children: eraseOptions.map(function (value, index) { return (_jsx(IconButton, __assign({ onClick: function () {
|
|
37
|
+
updateDrawPen({ target: { value: index === 0 ? 8 : 0 } });
|
|
38
|
+
setDrawingEnabled(true);
|
|
39
|
+
} }, { children: value }), index)); }) }))] })));
|
|
40
|
+
}
|
|
@@ -170,7 +170,7 @@ export function MroDrawToolkit(props) {
|
|
|
170
170
|
alignItems: "center",
|
|
171
171
|
gap: 4,
|
|
172
172
|
overflow: "visible"
|
|
173
|
-
} }, { children: [_jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "d" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Pen" }, { children: _jsx(IconButton, __assign({ "aria-label": "pen", size: "small", onClick: clickPen, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("pen")) }, { children: _jsx(DrawIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "d", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "r" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Rectangle" }, { children: _jsx(IconButton, __assign({ "aria-label": "rectangle", size: "small", onClick: clickRectangle, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("rectangle")) }, { children: _jsx(CropSquareOutlinedIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "r", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, shapeDraftActive: props.shapeDraftActive && drawShapeTool === "rectangle", onApplyShapeDraft: props.onApplyShapeDraft, onCancelShapeDraft: props.onCancelShapeDraft })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "l" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Ellipse" }, { children: _jsx(IconButton, __assign({ "aria-label": "ellipse", size: "small", onClick: clickEllipse, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("ellipse")) }, { children: _jsx(CircleOutlinedIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "l", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, shapeDraftActive: props.shapeDraftActive && drawShapeTool === "ellipse", onApplyShapeDraft: props.onApplyShapeDraft, onCancelShapeDraft: props.onCancelShapeDraft })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "e" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Eraser" }, { children: _jsx(IconButton, __assign({ "aria-label": "erase", size: "small", onClick: clickEraser, sx: toolBtnSx }, { children: filled || expandedOption !== "e" ? (_jsx(EraserIcon, {})) : (_jsx(AutoFixNormalOutlinedIcon, { sx: { color: ICON_COLOR } })) })) })), _jsx(EraserPlatte, { expandEraseOptions: expandedOption === "e", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled })] })), _jsx(Tooltip, __assign({ title: "Undo" }, { children: _jsx(IconButton, __assign({ "aria-label": "revert", size: "small", onClick: function () { return props.drawUndo(); }, sx: toolBtnSx }, { children: _jsx(ReplyIcon, { sx: { color: ICON_COLOR } }) })) })), _jsx(Tooltip, __assign({ title: "Save screenshot" }, { children: _jsx("span", { children: _jsx(IconButton, __assign({ "aria-label": "capture", size: "small", disabled: !vol, onClick: function () { return vol && props.nv.saveScene("".concat(vol.name, "_drawing.png")); }, sx: toolBtnSx }, { children: _jsx(CameraAltIcon, { sx: { color: ICON_COLOR } }) })) }) })), _jsx(Tooltip, __assign({ title: "Clear drawing" }, { children: _jsx(IconButton, __assign({ "aria-label": "delete", size: "small", onClick: function () {
|
|
173
|
+
} }, { children: [_jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "d" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Pen" }, { children: _jsx(IconButton, __assign({ "aria-label": "pen", size: "small", onClick: clickPen, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("pen")) }, { children: _jsx(DrawIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "d", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, showPenModes: true, penDrawMode: props.penDrawMode, onPenDrawModeChange: props.onPenDrawModeChange, polylineVertexCount: props.polylineVertexCount, onCancelPolyline: props.onCancelPolyline, onFinishPolyline: props.onFinishPolyline, onCloseFillPolyline: props.onCloseFillPolyline, brushSize: props.brushSize, updateBrushSize: props.updateBrushSize })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "r" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Rectangle" }, { children: _jsx(IconButton, __assign({ "aria-label": "rectangle", size: "small", onClick: clickRectangle, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("rectangle")) }, { children: _jsx(CropSquareOutlinedIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "r", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, shapeDraftActive: props.shapeDraftActive && drawShapeTool === "rectangle", onApplyShapeDraft: props.onApplyShapeDraft, onCancelShapeDraft: props.onCancelShapeDraft })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "l" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Ellipse" }, { children: _jsx(IconButton, __assign({ "aria-label": "ellipse", size: "small", onClick: clickEllipse, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("ellipse")) }, { children: _jsx(CircleOutlinedIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "l", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, shapeDraftActive: props.shapeDraftActive && drawShapeTool === "ellipse", onApplyShapeDraft: props.onApplyShapeDraft, onCancelShapeDraft: props.onCancelShapeDraft })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "e" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Eraser" }, { children: _jsx(IconButton, __assign({ "aria-label": "erase", size: "small", onClick: clickEraser, sx: toolBtnSx }, { children: filled || expandedOption !== "e" ? (_jsx(EraserIcon, {})) : (_jsx(AutoFixNormalOutlinedIcon, { sx: { color: ICON_COLOR } })) })) })), _jsx(EraserPlatte, { expandEraseOptions: expandedOption === "e", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, brushSize: props.brushSize, updateBrushSize: props.updateBrushSize })] })), _jsx(Tooltip, __assign({ title: "Undo" }, { children: _jsx(IconButton, __assign({ "aria-label": "revert", size: "small", onClick: function () { return props.drawUndo(); }, sx: toolBtnSx }, { children: _jsx(ReplyIcon, { sx: { color: ICON_COLOR } }) })) })), _jsx(Tooltip, __assign({ title: "Save screenshot" }, { children: _jsx("span", { children: _jsx(IconButton, __assign({ "aria-label": "capture", size: "small", disabled: !vol, onClick: function () { return vol && props.nv.saveScene("".concat(vol.name, "_drawing.png")); }, sx: toolBtnSx }, { children: _jsx(CameraAltIcon, { sx: { color: ICON_COLOR } }) })) }) })), _jsx(Tooltip, __assign({ title: "Clear drawing" }, { children: _jsx(IconButton, __assign({ "aria-label": "delete", size: "small", onClick: function () {
|
|
174
174
|
props.nv.clearDrawing();
|
|
175
175
|
props.resampleImage();
|
|
176
176
|
props.setDrawingChanged(false);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function isPolylinePenActive(nv: any): any;
|
|
2
|
+
export function isClickWithoutDrag(uiData: any, thresholdPx?: number): boolean;
|
|
3
|
+
export function axCorSagFromMouse(nv: any): any;
|
|
4
|
+
export function voxFromMouse(nv: any): any[] | null;
|
|
5
|
+
export function notifyPolylineChange(nv: any, count: any): void;
|
|
6
|
+
export function resetPolylineState(nv: any): void;
|
|
7
|
+
export function cancelPolyline(nv: any): void;
|
|
8
|
+
export function previewPolylineSegment(nv: any): void;
|
|
9
|
+
export function addPolylineVertex(nv: any): boolean;
|
|
10
|
+
export function finishPolyline(nv: any, { fillClosed }?: {
|
|
11
|
+
fillClosed?: boolean | undefined;
|
|
12
|
+
}): boolean;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
2
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
3
|
+
if (ar || !(i in from)) {
|
|
4
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
5
|
+
ar[i] = from[i];
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
9
|
+
};
|
|
10
|
+
import { NI_PEN_TYPE } from "./niivuePenType";
|
|
11
|
+
var CLICK_DRAG_PX = 5;
|
|
12
|
+
export function isPolylinePenActive(nv) {
|
|
13
|
+
return (nv.opts.polylinePenMode &&
|
|
14
|
+
nv.opts.drawingEnabled &&
|
|
15
|
+
nv.opts.penType === NI_PEN_TYPE.PEN);
|
|
16
|
+
}
|
|
17
|
+
export function isClickWithoutDrag(uiData, thresholdPx) {
|
|
18
|
+
if (thresholdPx === void 0) { thresholdPx = CLICK_DRAG_PX; }
|
|
19
|
+
var dx = uiData.dragStart[0] - uiData.dragEnd[0];
|
|
20
|
+
var dy = uiData.dragStart[1] - uiData.dragEnd[1];
|
|
21
|
+
return dx * dx + dy * dy <= thresholdPx * thresholdPx;
|
|
22
|
+
}
|
|
23
|
+
export function axCorSagFromMouse(nv) {
|
|
24
|
+
var _a;
|
|
25
|
+
var tile = nv.tileIndex(nv.mousePos[0], nv.mousePos[1]);
|
|
26
|
+
if (tile >= 0 && ((_a = nv.screenSlices) === null || _a === void 0 ? void 0 : _a[tile])) {
|
|
27
|
+
return nv.screenSlices[tile].axCorSag;
|
|
28
|
+
}
|
|
29
|
+
return nv.drawPenAxCorSag >= 0 ? nv.drawPenAxCorSag : 0;
|
|
30
|
+
}
|
|
31
|
+
export function voxFromMouse(nv) {
|
|
32
|
+
var frac = nv.canvasPos2frac(nv.mousePos);
|
|
33
|
+
if (!frac || frac[0] < 0)
|
|
34
|
+
return null;
|
|
35
|
+
var vox = nv.frac2vox(frac);
|
|
36
|
+
return [vox[0], vox[1], vox[2]];
|
|
37
|
+
}
|
|
38
|
+
export function notifyPolylineChange(nv, count) {
|
|
39
|
+
if (typeof nv.onPolylineChange === "function") {
|
|
40
|
+
nv.onPolylineChange(count);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function resetPolylineState(nv) {
|
|
44
|
+
nv._cloudMrPolylineVertices = [];
|
|
45
|
+
nv._cloudMrPolylineBaseBitmap = null;
|
|
46
|
+
nv._cloudMrPolylineSessionStartBitmap = null;
|
|
47
|
+
nv._cloudMrPolylineAxCorSag = -1;
|
|
48
|
+
notifyPolylineChange(nv, 0);
|
|
49
|
+
}
|
|
50
|
+
export function cancelPolyline(nv) {
|
|
51
|
+
if (nv._cloudMrPolylineSessionStartBitmap) {
|
|
52
|
+
nv.drawBitmap.set(nv._cloudMrPolylineSessionStartBitmap);
|
|
53
|
+
nv.refreshDrawing(true, false);
|
|
54
|
+
nv.drawScene();
|
|
55
|
+
}
|
|
56
|
+
resetPolylineState(nv);
|
|
57
|
+
}
|
|
58
|
+
export function previewPolylineSegment(nv) {
|
|
59
|
+
var verts = nv._cloudMrPolylineVertices;
|
|
60
|
+
if (!(verts === null || verts === void 0 ? void 0 : verts.length) || !nv._cloudMrPolylineBaseBitmap)
|
|
61
|
+
return;
|
|
62
|
+
var cursor = voxFromMouse(nv);
|
|
63
|
+
if (!cursor)
|
|
64
|
+
return;
|
|
65
|
+
nv.drawBitmap.set(nv._cloudMrPolylineBaseBitmap);
|
|
66
|
+
nv.drawPenAxCorSag = nv._cloudMrPolylineAxCorSag;
|
|
67
|
+
nv.drawPenLine(cursor, verts[verts.length - 1], nv.opts.penValue);
|
|
68
|
+
nv.refreshDrawing(false, false);
|
|
69
|
+
nv.drawScene();
|
|
70
|
+
}
|
|
71
|
+
export function addPolylineVertex(nv) {
|
|
72
|
+
var pt = voxFromMouse(nv);
|
|
73
|
+
if (!pt)
|
|
74
|
+
return false;
|
|
75
|
+
var penValue = nv.opts.penValue;
|
|
76
|
+
var verts = nv._cloudMrPolylineVertices || (nv._cloudMrPolylineVertices = []);
|
|
77
|
+
if (verts.length === 0) {
|
|
78
|
+
nv._cloudMrPolylineSessionStartBitmap = nv.drawBitmap.slice();
|
|
79
|
+
nv._cloudMrPolylineBaseBitmap = nv._cloudMrPolylineSessionStartBitmap.slice();
|
|
80
|
+
nv._cloudMrPolylineAxCorSag = axCorSagFromMouse(nv);
|
|
81
|
+
nv.drawPenAxCorSag = nv._cloudMrPolylineAxCorSag;
|
|
82
|
+
verts.push(pt);
|
|
83
|
+
nv.drawPt(pt[0], pt[1], pt[2], penValue);
|
|
84
|
+
nv.refreshDrawing(false, false);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
var prev = verts[verts.length - 1];
|
|
88
|
+
if (prev[0] === pt[0] && prev[1] === pt[1] && prev[2] === pt[2]) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
nv.drawPenAxCorSag = nv._cloudMrPolylineAxCorSag;
|
|
92
|
+
nv.drawPenLine(pt, prev, penValue);
|
|
93
|
+
verts.push(pt);
|
|
94
|
+
nv._cloudMrPolylineBaseBitmap = nv.drawBitmap.slice();
|
|
95
|
+
nv.refreshDrawing(false, false);
|
|
96
|
+
}
|
|
97
|
+
nv.drawScene();
|
|
98
|
+
notifyPolylineChange(nv, verts.length);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
export function finishPolyline(nv, _a) {
|
|
102
|
+
var _b = _a === void 0 ? {} : _a, _c = _b.fillClosed, fillClosed = _c === void 0 ? false : _c;
|
|
103
|
+
var verts = nv._cloudMrPolylineVertices;
|
|
104
|
+
if (!verts || verts.length < 2) {
|
|
105
|
+
resetPolylineState(nv);
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (fillClosed && verts.length >= 3) {
|
|
109
|
+
var first = verts[0];
|
|
110
|
+
var last = verts[verts.length - 1];
|
|
111
|
+
nv.drawPenAxCorSag = nv._cloudMrPolylineAxCorSag;
|
|
112
|
+
nv.drawPenLine(first, last, nv.opts.penValue);
|
|
113
|
+
nv.drawPenFillPts = verts.map(function (v) { return __spreadArray([], v, true); });
|
|
114
|
+
nv.drawPenFilled();
|
|
115
|
+
}
|
|
116
|
+
nv.drawAddUndoBitmap(nv.drawFillOverwrites);
|
|
117
|
+
if (typeof nv.onDrawingChanged === "function") {
|
|
118
|
+
nv.onDrawingChanged("draw");
|
|
119
|
+
}
|
|
120
|
+
resetPolylineState(nv);
|
|
121
|
+
nv.drawScene();
|
|
122
|
+
return true;
|
|
123
|
+
}
|