@@ -458,6 +458,8 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
458458
459459 private lastPixel = [ 0 , 0 ] as [ number , number ]
460460
461+ private readonly keysDown = new Set < string > ( )
462+
461463 private readonly defaultRoiStyle : dmv . viewer . ROIStyleOptions = {
462464 stroke : {
463465 color : DEFAULT_ROI_STROKE_COLOR ,
@@ -482,15 +484,16 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
482484 [ annotationUID : string ] : StyleOptions
483485 } = { }
484486
485- private readonly selectionColor : number [ ] = [ 140 , 184 , 198 ]
487+ private readonly selectionStrokeColor : number [ ] = [ 0 , 153 , 255 ]
488+ private readonly selectionFillColor : number [ ] = [ 255 , 255 , 255 ]
486489
487490 private readonly selectedRoiStyle : dmv . viewer . ROIStyleOptions = {
488- stroke : { color : [ ...this . selectionColor , 1 ] , width : 3 } ,
489- fill : { color : [ ...this . selectionColor , 0.2 ] } ,
491+ stroke : { color : [ ...this . selectionStrokeColor , 1 ] , width : 3 } ,
492+ fill : { color : [ ...this . selectionFillColor , 0.5 ] } ,
490493 image : {
491494 circle : {
492495 radius : 5 ,
493- fill : { color : [ ...this . selectionColor , 1 ] }
496+ fill : { color : [ ...this . selectionStrokeColor , 1 ] }
494497 }
495498 }
496499 }
@@ -548,7 +551,6 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
548551
549552 this . componentSetup = this . componentSetup . bind ( this )
550553 this . componentCleanup = this . componentCleanup . bind ( this )
551-
552554 this . onWindowResize = this . onWindowResize . bind ( this )
553555 this . handleRoiDrawing = this . handleRoiDrawing . bind ( this )
554556 this . handleRoiTranslation = this . handleRoiTranslation . bind ( this )
@@ -563,7 +565,6 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
563565 this . handleAnnotationEvaluationSelection = this . handleAnnotationEvaluationSelection . bind ( this )
564566 this . handleAnnotationEvaluationClearance = this . handleAnnotationEvaluationClearance . bind ( this )
565567 this . handleAnnotationConfigurationCompletion = this . handleAnnotationConfigurationCompletion . bind ( this )
566- this . handleAnnotationSelection = this . handleAnnotationSelection . bind ( this )
567568 this . handleAnnotationVisibilityChange = this . handleAnnotationVisibilityChange . bind ( this )
568569 this . handleAnnotationGroupVisibilityChange = this . handleAnnotationGroupVisibilityChange . bind ( this )
569570 this . handleAnnotationGroupStyleChange = this . handleAnnotationGroupStyleChange . bind ( this )
@@ -587,6 +588,7 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
587588 this . handlePresentationStateSelection = this . handlePresentationStateSelection . bind ( this )
588589 this . handlePresentationStateReset = this . handlePresentationStateReset . bind ( this )
589590 this . handleICCProfilesToggle = this . handleICCProfilesToggle . bind ( this )
591+ this . handleAnnotationSelection = this . handleAnnotationSelection . bind ( this )
590592
591593 const { volumeViewer, labelViewer } = _constructViewers ( {
592594 clients : this . props . clients ,
@@ -1680,21 +1682,98 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
16801682 }
16811683 }
16821684
1683- onRoiSelected = ( event : CustomEventInit ) : void => {
1684- const selectedRoi = event . detail . payload as dmv . roi . ROI | null
1685- if ( selectedRoi == null ) {
1686- this . setState ( {
1687- selectedRoiUIDs : new Set ( ) ,
1688- selectedRoi : undefined
1689- } )
1690- return
1685+ getUpdatedSelectedRois = ( newSelectedRoiUid ?: string ) : { selectedRoiUIDs : Set < string > , selectedRoi ?: dmv . roi . ROI } => {
1686+ const selectedRoiUid = newSelectedRoiUid
1687+ const emptySelection = {
1688+ selectedRoiUIDs : new Set < string > ( ) ,
1689+ selectedRoi : undefined
1690+ }
1691+
1692+ if ( selectedRoiUid === undefined ) {
1693+ return emptySelection
1694+ }
1695+
1696+ const selectedRoi = this . volumeViewer . getROI ( selectedRoiUid )
1697+ if ( selectedRoi === undefined ) {
1698+ return emptySelection
16911699 }
16921700
16931701 console . debug ( `selected ROI "${ selectedRoi . uid } "` )
1702+
1703+ if ( ! this . keysDown . has ( 'Shift' ) ) {
1704+ return {
1705+ selectedRoiUIDs : new Set ( [ selectedRoi . uid ] ) ,
1706+ selectedRoi
1707+ }
1708+ }
1709+
16941710 const oldSelectedRois = Array . from ( this . state . selectedRoiUIDs )
1695- this . setState ( {
1711+ return {
16961712 selectedRoiUIDs : new Set ( [ ...oldSelectedRois , selectedRoi . uid ] ) ,
1697- selectedRoi : selectedRoi
1713+ selectedRoi
1714+ }
1715+ }
1716+
1717+ resetUnselectedRoiStyles = ( selectionState : { selectedRoiUIDs : Set < string > } ) : void => {
1718+ this . volumeViewer . getAllROIs ( ) . forEach ( roi => {
1719+ const uid = roi . uid
1720+
1721+ if ( selectionState . selectedRoiUIDs . has ( uid ) || ! this . state . visibleRoiUIDs . has ( uid ) ) {
1722+ return
1723+ }
1724+
1725+ const key = _getRoiKey ( roi )
1726+ const style = this . getRoiStyle ( key )
1727+ this . volumeViewer . setROIStyle ( uid , style )
1728+ } )
1729+ }
1730+
1731+ onMapClicked = ( event : CustomEventInit ) : void => {
1732+ const roisClicked = ( event . detail ?. payload ?. rois ?? [ ] ) as dmv . roi . ROI [ ]
1733+
1734+ if ( roisClicked . length !== 0 ) {
1735+ return
1736+ }
1737+
1738+ const updatedSelectedRois = this . getUpdatedSelectedRois ( )
1739+ this . setState ( updatedSelectedRois )
1740+
1741+ // @ts -expect-error
1742+ this . volumeViewer . clearSelections ( )
1743+
1744+ this . resetUnselectedRoiStyles ( updatedSelectedRois )
1745+ }
1746+
1747+ onRoiSelected = ( event : CustomEventInit ) : void => {
1748+ const selectedRoiUid = event . detail ?. payload ?. uid as string
1749+ const updatedSelectedRois = this . getUpdatedSelectedRois ( selectedRoiUid )
1750+ this . setState ( updatedSelectedRois )
1751+
1752+ this . resetUnselectedRoiStyles ( updatedSelectedRois )
1753+ }
1754+
1755+ handleAnnotationSelection ( uid : string ) : void {
1756+ // @ts -expect-error
1757+ this . volumeViewer . clearSelections ( )
1758+
1759+ const updatedSelectedRois = this . getUpdatedSelectedRois ( uid )
1760+ this . setState ( updatedSelectedRois )
1761+ this . volumeViewer . getAllROIs ( ) . forEach ( ( roi ) => {
1762+ let style = { }
1763+ if ( updatedSelectedRois . selectedRoiUIDs . has ( roi . uid ) ) {
1764+ style = this . selectedRoiStyle
1765+ this . setState ( state => {
1766+ const visibleRoiUIDs = state . visibleRoiUIDs
1767+ visibleRoiUIDs . add ( roi . uid )
1768+ return { visibleRoiUIDs }
1769+ } )
1770+ } else {
1771+ if ( this . state . visibleRoiUIDs . has ( roi . uid ) ) {
1772+ const key = _getRoiKey ( roi )
1773+ style = this . getRoiStyle ( key )
1774+ }
1775+ }
1776+ this . volumeViewer . setROIStyle ( roi . uid , style )
16981777 } )
16991778 }
17001779
@@ -1834,6 +1913,10 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
18341913 'dicommicroscopyviewer_roi_drawn' ,
18351914 this . onRoiDrawn
18361915 )
1916+ document . body . removeEventListener (
1917+ 'dicommicroscopyviewer_viewport_clicked' ,
1918+ this . onMapClicked
1919+ )
18371920 document . body . removeEventListener (
18381921 'dicommicroscopyviewer_roi_selected' ,
18391922 this . onRoiSelected
@@ -1874,6 +1957,10 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
18741957 'keyup' ,
18751958 this . onKeyUp
18761959 )
1960+ document . body . removeEventListener (
1961+ 'keyup' ,
1962+ this . onKeyDown
1963+ )
18771964 window . removeEventListener ( 'resize' , this . onWindowResize )
18781965
18791966 this . volumeViewer . cleanup ( )
@@ -1890,7 +1977,12 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
18901977 */
18911978 }
18921979
1980+ onKeyDown = ( event : KeyboardEvent ) : void => {
1981+ this . keysDown . add ( event . key )
1982+ }
1983+
18931984 onKeyUp = ( event : KeyboardEvent ) : void => {
1985+ this . keysDown . delete ( event . key )
18941986 if ( event . key === 'Escape' ) {
18951987 if ( this . state . isRoiDrawingActive ) {
18961988 console . info ( 'deactivate drawing of ROIs' )
@@ -1949,6 +2041,10 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
19492041 'dicommicroscopyviewer_roi_selected' ,
19502042 this . onRoiSelected
19512043 )
2044+ document . body . addEventListener (
2045+ 'dicommicroscopyviewer_viewport_clicked' ,
2046+ this . onMapClicked
2047+ )
19522048 document . body . addEventListener (
19532049 'dicommicroscopyviewer_roi_double_clicked' ,
19542050 this . onRoiDoubleClicked
@@ -1993,6 +2089,10 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
19932089 'keyup' ,
19942090 this . onKeyUp
19952091 )
2092+ document . body . addEventListener (
2093+ 'keydown' ,
2094+ this . onKeyDown
2095+ )
19962096 window . addEventListener ( 'beforeunload' , this . componentCleanup )
19972097 window . addEventListener ( 'resize' , this . onWindowResize )
19982098 }
@@ -2524,32 +2624,6 @@ class SlideViewer extends React.Component<SlideViewerProps, SlideViewerState> {
25242624 } )
25252625 }
25262626
2527- /**
2528- * Handler that gets called when an annotation has been selected from the
2529- * current list of annotations.
2530- */
2531- handleAnnotationSelection ( { roiUID } : { roiUID : string } ) : void {
2532- console . log ( `selected ROI ${ roiUID } ` )
2533- this . setState ( { selectedRoiUIDs : new Set ( [ roiUID ] ) } )
2534- this . volumeViewer . getAllROIs ( ) . forEach ( ( roi ) => {
2535- let style = { }
2536- if ( roi . uid === roiUID ) {
2537- style = this . selectedRoiStyle
2538- this . setState ( state => {
2539- const visibleRoiUIDs = state . visibleRoiUIDs
2540- visibleRoiUIDs . add ( roi . uid )
2541- return { visibleRoiUIDs }
2542- } )
2543- } else {
2544- if ( this . state . visibleRoiUIDs . has ( roi . uid ) ) {
2545- const key = _getRoiKey ( roi )
2546- style = this . getRoiStyle ( key )
2547- }
2548- }
2549- this . volumeViewer . setROIStyle ( roi . uid , style )
2550- } )
2551- }
2552-
25532627 /**
25542628 * Handle toggling of annotation visibility, i.e., whether a given
25552629 * annotation should be either displayed or hidden by the viewer.
0 commit comments