From cedfc4760252f42392874d8f00d012c310b3bec3 Mon Sep 17 00:00:00 2001
From: Xiao Gui <xgui3783@gmail.com>
Date: Mon, 5 Oct 2020 12:47:05 +0200
Subject: [PATCH] chore: disallow allen v3 root to be selected

---
 src/atlasViewer/atlasViewer.component.ts     |  4 +--
 src/atlasViewer/mouseOver.directive.ts       |  4 +--
 src/res/ext/allenMouse.json                  |  1 +
 src/services/state/uiState/selectors.spec.ts | 27 ++++++++++++++++++++
 src/services/state/uiState/selectors.ts      | 16 ++++++++++++
 5 files changed, 48 insertions(+), 4 deletions(-)
 create mode 100644 src/services/state/uiState/selectors.spec.ts

diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts
index e77718d7a..deff73cac 100644
--- a/src/atlasViewer/atlasViewer.component.ts
+++ b/src/atlasViewer/atlasViewer.component.ts
@@ -44,6 +44,7 @@ import { viewerStateSetSelectedRegions, viewerStateRemoveAdditionalLayer, viewer
 import { viewerStateGetOverlayingAdditionalParcellations, viewerStateParcVersionSelector } from "src/services/state/viewerState/selectors";
 import { ngViewerSelectorClearViewEntries } from "src/services/state/ngViewerState/selectors";
 import { ngViewerActionClearView } from "src/services/state/ngViewerState/actions";
+import { uiStateMouseOverSegmentsSelector } from "src/services/state/uiState/selectors";
 
 /**
  * TODO
@@ -193,8 +194,7 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
 
     // TODO temporary hack. even though the front octant is hidden, it seems if a mesh is present, hover will select the said mesh
     this.onhoverSegments$ = this.store.pipe(
-      select('uiState'),
-      select('mouseOverSegments'),
+      select(uiStateMouseOverSegmentsSelector),
       filter(v => !!v),
       distinctUntilChanged((o, n) => o.length === n.length && n.every(segment => o.find(oSegment => oSegment.layer.name === segment.layer.name && oSegment.segment === segment.segment) ) ),
       /* cannot filter by state, as the template expects a default value, or it will throw ExpressionChangedAfterItHasBeenCheckedError */
diff --git a/src/atlasViewer/mouseOver.directive.ts b/src/atlasViewer/mouseOver.directive.ts
index 0d31a3107..e648b53ba 100644
--- a/src/atlasViewer/mouseOver.directive.ts
+++ b/src/atlasViewer/mouseOver.directive.ts
@@ -5,6 +5,7 @@ import { combineLatest, merge, Observable } from "rxjs";
 import { distinctUntilChanged, filter, map, scan, shareReplay, startWith, withLatestFrom } from "rxjs/operators";
 import { TransformOnhoverSegmentPipe } from "src/atlasViewer/onhoverSegment.pipe";
 import { LoggingService } from "src/logging";
+import { uiStateMouseOverSegmentsSelector } from "src/services/state/uiState/selectors";
 import { getNgIdLabelIndexFromId } from "src/services/stateStore.service";
 
 /**
@@ -85,8 +86,7 @@ export class MouseHoverDirective {
     )
 
     const onHoverSegments$ = this.store$.pipe(
-      select('uiState'),
-      select('mouseOverSegments'),
+      select(uiStateMouseOverSegmentsSelector),
       filter(v => !!v),
       withLatestFrom(
         this.store$.pipe(
diff --git a/src/res/ext/allenMouse.json b/src/res/ext/allenMouse.json
index 09fd34b91..9c9a5ec85 100644
--- a/src/res/ext/allenMouse.json
+++ b/src/res/ext/allenMouse.json
@@ -33,6 +33,7 @@
           ],
           "name": "root",
           "labelIndex": 997,
+          "unselectable": true,
           "relatedAreas": [
             {
               "name": "Whole brain",
diff --git a/src/services/state/uiState/selectors.spec.ts b/src/services/state/uiState/selectors.spec.ts
new file mode 100644
index 000000000..8f26ad8b2
--- /dev/null
+++ b/src/services/state/uiState/selectors.spec.ts
@@ -0,0 +1,27 @@
+import { uiStateMouseOverSegmentsSelector } from './selectors'
+
+describe('> uiState/selectors.ts', () => {
+  describe('> mouseOverSegments', () => {
+    it('> should filter out regions explicitly designated as unselectable', () => {
+      const unSelSeg = {
+        segment: {
+          unselectable: true
+        }
+      }
+
+      const selSeg0 = {
+        segment: 1
+      }
+
+      const selSeg1 = {
+        segment: {
+          name: 'hello world',
+          unselectable: false
+        }
+      }
+      const filteredResult = uiStateMouseOverSegmentsSelector.projector([unSelSeg, selSeg0, selSeg1])
+
+      expect(filteredResult).toEqual([selSeg0, selSeg1])
+    })
+  })
+})
diff --git a/src/services/state/uiState/selectors.ts b/src/services/state/uiState/selectors.ts
index a4db9adfc..a004f0598 100644
--- a/src/services/state/uiState/selectors.ts
+++ b/src/services/state/uiState/selectors.ts
@@ -4,3 +4,19 @@ export const uiStatePreviewingDatasetFilesSelector = createSelector(
   state => state['uiState'],
   uiState => uiState['previewingDatasetFiles']
 )
+
+export const uiStateMouseOverSegmentsSelector = createSelector(
+  state => state['uiState']['mouseOverSegments'],
+  mouseOverSegments => {
+    /**
+     * filter out the regions explicitly declared `unselectable`
+     */
+    return mouseOverSegments
+      .filter(({ segment }) => {
+        if (typeof segment === 'object' && segment !== null) {
+          if (segment.unselectable) return false
+        }
+        return true
+      })
+  }
+)
-- 
GitLab