cloudmr-ux 4.6.3 → 4.6.5
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.js +1 -1
- package/dist/CmrComponents/niivue-viewer/CloudMrNiivueViewer.js +15 -0
- package/dist/CmrComponents/niivue-viewer/NiivuePatcher.js +65 -17
- package/dist/CmrComponents/niivue-viewer/PenDraftOverlay.d.ts +2 -3
- package/dist/CmrComponents/niivue-viewer/PenDraftOverlay.js +2 -7
- package/dist/CmrComponents/niivue-viewer/ShapeDraftOverlay.d.ts +2 -3
- package/dist/CmrComponents/niivue-viewer/ShapeDraftOverlay.js +2 -7
- package/package.json +1 -1
|
@@ -186,7 +186,7 @@ export function CloudMrNiivuePanel(props) {
|
|
|
186
186
|
left: 0,
|
|
187
187
|
width: "100%",
|
|
188
188
|
height: "100%"
|
|
189
|
-
} }), props.shapeDraft && (_jsx(ShapeDraftOverlay, { nv: props.nv, draft: props.shapeDraft, onDraftChange: props.onShapeDraftChange,
|
|
189
|
+
} }), props.shapeDraft && (_jsx(ShapeDraftOverlay, { nv: props.nv, draft: props.shapeDraft, onDraftChange: props.onShapeDraftChange, overlayKey: props.mms })), props.penDraft && (_jsx(PenDraftOverlay, { nv: props.nv, draft: props.penDraft, onDraftChange: props.onPenDraftChange, overlayKey: props.mms }))] }))] })), _jsxs(Box, __assign({ sx: {
|
|
190
190
|
width: {
|
|
191
191
|
xs: "100%",
|
|
192
192
|
md: "35%"
|
|
@@ -586,6 +586,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
586
586
|
setPenDraft(null);
|
|
587
587
|
penDraftRef.current = null;
|
|
588
588
|
nv._cloudMrPenDraftActive = false;
|
|
589
|
+
clearActivePenDraftRef();
|
|
589
590
|
setPolylineVertexCount(0);
|
|
590
591
|
}
|
|
591
592
|
if (shapeDraftRef.current) {
|
|
@@ -610,6 +611,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
610
611
|
setPenDraft(null);
|
|
611
612
|
penDraftRef.current = null;
|
|
612
613
|
nv._cloudMrPenDraftActive = false;
|
|
614
|
+
clearActivePenDraftRef();
|
|
613
615
|
}
|
|
614
616
|
setDrawShapeTool(null);
|
|
615
617
|
nv.opts.penType = NI_PEN_TYPE.PEN;
|
|
@@ -641,6 +643,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
641
643
|
setPenDraft(null);
|
|
642
644
|
penDraftRef.current = null;
|
|
643
645
|
nv._cloudMrPenDraftActive = false;
|
|
646
|
+
clearActivePenDraftRef();
|
|
644
647
|
}
|
|
645
648
|
nvUpdateDrawPen({ target: { value: 8 } });
|
|
646
649
|
nvSetDrawingEnabled(true);
|
|
@@ -838,6 +841,12 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
838
841
|
function clearActiveShapeDraftRef() {
|
|
839
842
|
nv._cloudMrActiveShapeDraft = null;
|
|
840
843
|
}
|
|
844
|
+
function syncActivePenDraftRef() {
|
|
845
|
+
nv._cloudMrActivePenDraft = penDraftRef.current;
|
|
846
|
+
}
|
|
847
|
+
function clearActivePenDraftRef() {
|
|
848
|
+
nv._cloudMrActivePenDraft = null;
|
|
849
|
+
}
|
|
841
850
|
function cancelPenDraftHandler() {
|
|
842
851
|
var _a;
|
|
843
852
|
var draft = penDraftRef.current;
|
|
@@ -851,6 +860,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
851
860
|
setPenDraft(null);
|
|
852
861
|
penDraftRef.current = null;
|
|
853
862
|
nv._cloudMrPenDraftActive = false;
|
|
863
|
+
clearActivePenDraftRef();
|
|
854
864
|
if (drawShapeToolRef.current === "pen") {
|
|
855
865
|
nvSetDrawingEnabled(true);
|
|
856
866
|
}
|
|
@@ -868,6 +878,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
868
878
|
setPenDraft(null);
|
|
869
879
|
penDraftRef.current = null;
|
|
870
880
|
nv._cloudMrPenDraftActive = false;
|
|
881
|
+
clearActivePenDraftRef();
|
|
871
882
|
setDrawingChanged(true);
|
|
872
883
|
if (drawShapeToolRef.current === "pen") {
|
|
873
884
|
nvSetDrawingEnabled(true);
|
|
@@ -884,6 +895,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
884
895
|
function onPenDraftChange(draft) {
|
|
885
896
|
setPenDraft(draft);
|
|
886
897
|
penDraftRef.current = draft;
|
|
898
|
+
syncActivePenDraftRef();
|
|
887
899
|
if (draft.kind === "polyline") {
|
|
888
900
|
syncPolylineDraftToNv(nv, draft);
|
|
889
901
|
}
|
|
@@ -895,6 +907,7 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
895
907
|
setPenDraft(draft);
|
|
896
908
|
penDraftRef.current = draft;
|
|
897
909
|
nv._cloudMrPenDraftActive = true;
|
|
910
|
+
syncActivePenDraftRef();
|
|
898
911
|
nvSetDrawingEnabled(false);
|
|
899
912
|
};
|
|
900
913
|
nv.onPolylineChange = function (count) {
|
|
@@ -909,11 +922,13 @@ export default function CloudMrNiivueViewer(props) {
|
|
|
909
922
|
if (draft) {
|
|
910
923
|
setPenDraft(draft);
|
|
911
924
|
penDraftRef.current = draft;
|
|
925
|
+
syncActivePenDraftRef();
|
|
912
926
|
}
|
|
913
927
|
}
|
|
914
928
|
else if (((_b = penDraftRef.current) === null || _b === void 0 ? void 0 : _b.kind) === "polyline") {
|
|
915
929
|
setPenDraft(null);
|
|
916
930
|
penDraftRef.current = null;
|
|
931
|
+
clearActivePenDraftRef();
|
|
917
932
|
}
|
|
918
933
|
};
|
|
919
934
|
function cancelShapeDraft() {
|
|
@@ -1481,6 +1481,23 @@ function isClickOnActiveShapeDraft(nv) {
|
|
|
1481
1481
|
return isVoxelPartOfDraft(nv, draft, vox);
|
|
1482
1482
|
}
|
|
1483
1483
|
|
|
1484
|
+
function isClickOnActivePenDraft(nv) {
|
|
1485
|
+
const draft = nv._cloudMrActivePenDraft;
|
|
1486
|
+
if (!draft || !nv._cloudMrPenDraftActive) return false;
|
|
1487
|
+
const vox = voxFromMouse(nv);
|
|
1488
|
+
if (!vox) return false;
|
|
1489
|
+
return isVoxelPartOfDraft(nv, draft, vox);
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
function voxelLabelAt(nv, vox) {
|
|
1493
|
+
const dims = nv.back?.dims;
|
|
1494
|
+
if (!dims || !nv.drawBitmap || !vox) return 0;
|
|
1495
|
+
const dx = dims[1];
|
|
1496
|
+
const dy = dims[2];
|
|
1497
|
+
const idx = vox[0] + vox[1] * dx + vox[2] * dx * dy;
|
|
1498
|
+
return nv.drawBitmap[idx] || 0;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1484
1501
|
function canReopenShapeDraftOnClick(nv) {
|
|
1485
1502
|
const penType = nv.opts.penType;
|
|
1486
1503
|
return (
|
|
@@ -1506,18 +1523,25 @@ function cloudMrOpenShapeDraftFromClick(nv) {
|
|
|
1506
1523
|
/**
|
|
1507
1524
|
* Re-enter rectangle/ellipse edit mode when clicking an existing shape ROI.
|
|
1508
1525
|
*/
|
|
1509
|
-
function
|
|
1510
|
-
if (
|
|
1526
|
+
function cloudMrTryOpenShapeDraftOnMouseDown(nv) {
|
|
1527
|
+
if (nv._cloudMrShapeDraftActive || nv._cloudMrPenDraftActive) {
|
|
1528
|
+
return false;
|
|
1529
|
+
}
|
|
1530
|
+
if (!canReopenShapeDraftOnClick(nv)) {
|
|
1531
|
+
return false;
|
|
1532
|
+
}
|
|
1533
|
+
const vox = voxFromMouse(nv);
|
|
1534
|
+
if (!vox || !voxelLabelAt(nv, vox)) {
|
|
1511
1535
|
return false;
|
|
1512
1536
|
}
|
|
1513
1537
|
return cloudMrOpenShapeDraftFromClick(nv);
|
|
1514
1538
|
}
|
|
1515
1539
|
|
|
1516
1540
|
/**
|
|
1517
|
-
*
|
|
1518
|
-
*
|
|
1541
|
+
* Click-away exits shape edit mode; clicking another shape selects it for editing.
|
|
1542
|
+
* Disconnected same-color shapes are distinguished by flood-fill from the click point.
|
|
1519
1543
|
*/
|
|
1520
|
-
function
|
|
1544
|
+
function cloudMrHandleShapeDraftClickOnMouseDown(nv) {
|
|
1521
1545
|
if (!nv._cloudMrShapeDraftActive || nv._cloudMrPenDraftActive) {
|
|
1522
1546
|
return false;
|
|
1523
1547
|
}
|
|
@@ -1526,29 +1550,55 @@ function cloudMrTrySwitchShapeDraftOnMouseDown(nv) {
|
|
|
1526
1550
|
}
|
|
1527
1551
|
|
|
1528
1552
|
const vox = voxFromMouse(nv);
|
|
1529
|
-
if (!vox
|
|
1553
|
+
if (!vox) {
|
|
1554
|
+
return false;
|
|
1555
|
+
}
|
|
1556
|
+
if (isClickOnActiveShapeDraft(nv)) {
|
|
1530
1557
|
return false;
|
|
1531
1558
|
}
|
|
1532
1559
|
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1560
|
+
if (typeof nv.onApplyActiveDraft === "function") {
|
|
1561
|
+
nv.onApplyActiveDraft();
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
if (voxelLabelAt(nv, vox) > 0) {
|
|
1565
|
+
cloudMrOpenShapeDraftFromClick(nv);
|
|
1566
|
+
}
|
|
1567
|
+
return true;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
/** Click-away applies a pen draft without starting a new stroke. */
|
|
1571
|
+
function cloudMrHandlePenDraftClickOnMouseDown(nv) {
|
|
1572
|
+
if (!nv._cloudMrPenDraftActive) {
|
|
1573
|
+
return false;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
const vox = voxFromMouse(nv);
|
|
1577
|
+
if (!vox) {
|
|
1578
|
+
return false;
|
|
1579
|
+
}
|
|
1580
|
+
if (isClickOnActivePenDraft(nv)) {
|
|
1539
1581
|
return false;
|
|
1540
1582
|
}
|
|
1541
1583
|
|
|
1542
1584
|
if (typeof nv.onApplyActiveDraft === "function") {
|
|
1543
1585
|
nv.onApplyActiveDraft();
|
|
1544
1586
|
}
|
|
1545
|
-
return
|
|
1587
|
+
return true;
|
|
1546
1588
|
}
|
|
1547
1589
|
|
|
1548
1590
|
const _mouseDownListener = Niivue.prototype.mouseDownListener;
|
|
1549
1591
|
Niivue.prototype.mouseDownListener = function cloudMrMouseDownListener(e) {
|
|
1550
|
-
if (e.button === 0
|
|
1551
|
-
|
|
1592
|
+
if (e.button === 0) {
|
|
1593
|
+
if (cloudMrHandleShapeDraftClickOnMouseDown(this)) {
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
if (cloudMrHandlePenDraftClickOnMouseDown(this)) {
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
if (cloudMrTryOpenShapeDraftOnMouseDown(this)) {
|
|
1600
|
+
return;
|
|
1601
|
+
}
|
|
1552
1602
|
}
|
|
1553
1603
|
if (shouldDeferFreehandCommit(this) && this.drawBitmap) {
|
|
1554
1604
|
this._cloudMrFreehandSessionStartBitmap = this.drawBitmap.slice();
|
|
@@ -1618,14 +1668,12 @@ Niivue.prototype.mouseUpListener = function cloudMrMouseUpListener() {
|
|
|
1618
1668
|
}
|
|
1619
1669
|
|
|
1620
1670
|
if (!pendingDraft?.baseBitmap) {
|
|
1621
|
-
cloudMrTryReopenShapeDraftOnClick(this);
|
|
1622
1671
|
return;
|
|
1623
1672
|
}
|
|
1624
1673
|
if (isDraftTooSmall(pendingDraft.ptA, pendingDraft.ptB)) {
|
|
1625
1674
|
this.drawBitmap.set(pendingDraft.baseBitmap);
|
|
1626
1675
|
this.refreshDrawing(true, false);
|
|
1627
1676
|
this.drawScene();
|
|
1628
|
-
cloudMrTryReopenShapeDraftOnClick(this);
|
|
1629
1677
|
return;
|
|
1630
1678
|
}
|
|
1631
1679
|
this._cloudMrSuppressDrawingChangedMouseUp = true;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Adjust handles for polyline (vertex drag) or freehand (move only) drafts.
|
|
3
|
-
* @param {{ nv: any, draft: any, onDraftChange: (d: any) => void,
|
|
3
|
+
* @param {{ nv: any, draft: any, onDraftChange: (d: any) => void, overlayKey?: unknown }} props
|
|
4
4
|
*/
|
|
5
|
-
export function PenDraftOverlay({ nv, draft, onDraftChange,
|
|
5
|
+
export function PenDraftOverlay({ nv, draft, onDraftChange, overlayKey }: {
|
|
6
6
|
nv: any;
|
|
7
7
|
draft: any;
|
|
8
8
|
onDraftChange: (d: any) => void;
|
|
9
|
-
onApplyDraft?: (() => void) | undefined;
|
|
10
9
|
overlayKey?: unknown;
|
|
11
10
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
12
11
|
export default PenDraftOverlay;
|
|
@@ -29,10 +29,10 @@ function cloneFreehandDraft(draft) {
|
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Adjust handles for polyline (vertex drag) or freehand (move only) drafts.
|
|
32
|
-
* @param {{ nv: any, draft: any, onDraftChange: (d: any) => void,
|
|
32
|
+
* @param {{ nv: any, draft: any, onDraftChange: (d: any) => void, overlayKey?: unknown }} props
|
|
33
33
|
*/
|
|
34
34
|
export function PenDraftOverlay(_a) {
|
|
35
|
-
var nv = _a.nv, draft = _a.draft, onDraftChange = _a.onDraftChange,
|
|
35
|
+
var nv = _a.nv, draft = _a.draft, onDraftChange = _a.onDraftChange, overlayKey = _a.overlayKey;
|
|
36
36
|
var dragRef = useRef(null);
|
|
37
37
|
var draftRef = useRef(draft);
|
|
38
38
|
draftRef.current = draft;
|
|
@@ -110,7 +110,6 @@ export function PenDraftOverlay(_a) {
|
|
|
110
110
|
onDraftChange(nextDraft);
|
|
111
111
|
}, [nv, onDraftChange]);
|
|
112
112
|
finishDragRef.current = function () {
|
|
113
|
-
var hadDrag = dragRef.current != null;
|
|
114
113
|
dragRef.current = null;
|
|
115
114
|
if (onPointerMoveRef.current) {
|
|
116
115
|
window.removeEventListener("pointermove", onPointerMoveRef.current);
|
|
@@ -118,10 +117,6 @@ export function PenDraftOverlay(_a) {
|
|
|
118
117
|
if (finishDragRef.current) {
|
|
119
118
|
window.removeEventListener("pointerup", finishDragRef.current);
|
|
120
119
|
}
|
|
121
|
-
// Auto-apply as soon as the user releases the handle after a move/resize
|
|
122
|
-
if (hadDrag && onApplyDraft) {
|
|
123
|
-
onApplyDraft();
|
|
124
|
-
}
|
|
125
120
|
};
|
|
126
121
|
onPointerMoveRef.current = function (event) {
|
|
127
122
|
var drag = dragRef.current;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay handles for adjusting a rectangle/ellipse draft before commit.
|
|
3
|
-
* @param {{ nv: any, draft: import('./shapeDraftUtils').ShapeDraft, onDraftChange: (d: any) => void,
|
|
3
|
+
* @param {{ nv: any, draft: import('./shapeDraftUtils').ShapeDraft, onDraftChange: (d: any) => void, overlayKey?: unknown }} props
|
|
4
4
|
*/
|
|
5
|
-
export function ShapeDraftOverlay({ nv, draft, onDraftChange,
|
|
5
|
+
export function ShapeDraftOverlay({ nv, draft, onDraftChange, overlayKey }: {
|
|
6
6
|
nv: any;
|
|
7
7
|
draft: import('./shapeDraftUtils').ShapeDraft;
|
|
8
8
|
onDraftChange: (d: any) => void;
|
|
9
|
-
onApplyDraft?: (() => void) | undefined;
|
|
10
9
|
overlayKey?: unknown;
|
|
11
10
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
12
11
|
export default ShapeDraftOverlay;
|
|
@@ -25,11 +25,11 @@ var HANDLE_SIZE = 10;
|
|
|
25
25
|
var ACCENT = "#580f8b";
|
|
26
26
|
/**
|
|
27
27
|
* Overlay handles for adjusting a rectangle/ellipse draft before commit.
|
|
28
|
-
* @param {{ nv: any, draft: import('./shapeDraftUtils').ShapeDraft, onDraftChange: (d: any) => void,
|
|
28
|
+
* @param {{ nv: any, draft: import('./shapeDraftUtils').ShapeDraft, onDraftChange: (d: any) => void, overlayKey?: unknown }} props
|
|
29
29
|
*/
|
|
30
30
|
export function ShapeDraftOverlay(_a) {
|
|
31
31
|
var _b;
|
|
32
|
-
var nv = _a.nv, draft = _a.draft, onDraftChange = _a.onDraftChange,
|
|
32
|
+
var nv = _a.nv, draft = _a.draft, onDraftChange = _a.onDraftChange, overlayKey = _a.overlayKey;
|
|
33
33
|
var dragRef = useRef(null);
|
|
34
34
|
var draftRef = useRef(draft);
|
|
35
35
|
draftRef.current = draft;
|
|
@@ -84,7 +84,6 @@ export function ShapeDraftOverlay(_a) {
|
|
|
84
84
|
onDraftChange(nextDraft);
|
|
85
85
|
}, [nv, onDraftChange]);
|
|
86
86
|
finishDragRef.current = function () {
|
|
87
|
-
var hadDrag = dragRef.current != null;
|
|
88
87
|
dragRef.current = null;
|
|
89
88
|
if (onPointerMoveRef.current) {
|
|
90
89
|
window.removeEventListener("pointermove", onPointerMoveRef.current);
|
|
@@ -92,10 +91,6 @@ export function ShapeDraftOverlay(_a) {
|
|
|
92
91
|
if (finishDragRef.current) {
|
|
93
92
|
window.removeEventListener("pointerup", finishDragRef.current);
|
|
94
93
|
}
|
|
95
|
-
// Auto-apply as soon as the user releases the handle after a move/resize
|
|
96
|
-
if (hadDrag && onApplyDraft) {
|
|
97
|
-
onApplyDraft();
|
|
98
|
-
}
|
|
99
94
|
};
|
|
100
95
|
onPointerMoveRef.current = function (event) {
|
|
101
96
|
var drag = dragRef.current;
|