From bfec0476c52a5d4c3edde9ad6366bf5e32aeb1b6 Mon Sep 17 00:00:00 2001
From: Alexander Rose <alexander.rose@weirdbyte.de>
Date: Mon, 11 Jun 2018 07:38:30 +0200
Subject: [PATCH] added EmptyLoci

---
 src/mol-geo/representation/index.ts           |  2 +-
 src/mol-geo/representation/structure/bond.ts  |  4 +-
 src/mol-geo/representation/structure/index.ts |  6 +--
 src/mol-geo/representation/structure/point.ts |  4 +-
 .../representation/structure/spacefill.ts     |  4 +-
 src/mol-geo/representation/volume/index.ts    |  6 +--
 src/mol-geo/representation/volume/surface.ts  |  4 +-
 src/mol-model/loci.ts                         |  9 ++++-
 src/mol-view/label.ts                         | 37 +++++++++++--------
 9 files changed, 45 insertions(+), 31 deletions(-)

diff --git a/src/mol-geo/representation/index.ts b/src/mol-geo/representation/index.ts
index 4ef62c695..0f0e04bf4 100644
--- a/src/mol-geo/representation/index.ts
+++ b/src/mol-geo/representation/index.ts
@@ -16,6 +16,6 @@ export interface Representation<D, P extends RepresentationProps = {}> {
     renderObjects: ReadonlyArray<RenderObject>
     create: (data: D, props?: P) => Task<void>
     update: (props: P) => Task<void>
-    getLoci: (pickingId: PickingId) => Loci | null
+    getLoci: (pickingId: PickingId) => Loci
     mark: (loci: Loci, action: MarkerAction) => void
 }
\ No newline at end of file
diff --git a/src/mol-geo/representation/structure/bond.ts b/src/mol-geo/representation/structure/bond.ts
index 492731141..69ac57911 100644
--- a/src/mol-geo/representation/structure/bond.ts
+++ b/src/mol-geo/representation/structure/bond.ts
@@ -23,7 +23,7 @@ import { MeshBuilder } from '../../shape/mesh-builder';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { createUniformColor } from '../../util/color-data';
 import { defaults } from 'mol-util';
-import { Loci, isEveryLoci } from 'mol-model/loci';
+import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci';
 import { MarkerAction, applyMarkerAction, createMarkers } from '../../util/marker-data';
 
 function createBondMesh(unit: Unit, mesh?: Mesh) {
@@ -174,7 +174,7 @@ export default function BondUnitsRepresentation(): UnitsRepresentation<BondProps
                     bIndex: unit.links.b[elementId]
                 }])
             }
-            return null
+            return EmptyLoci
         },
         mark(loci: Loci, action: MarkerAction) {
             const group = currentGroup
diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-geo/representation/structure/index.ts
index 756fc6ece..4716fc2c4 100644
--- a/src/mol-geo/representation/structure/index.ts
+++ b/src/mol-geo/representation/structure/index.ts
@@ -11,14 +11,14 @@ import { RenderObject } from 'mol-gl/render-object';
 import { Representation, RepresentationProps } from '..';
 import { ColorTheme } from '../../theme';
 import { PickingId } from '../../util/picking';
-import { Loci } from 'mol-model/loci';
+import { Loci, EmptyLoci } from 'mol-model/loci';
 import { MarkerAction } from '../../util/marker-data';
 
 export interface UnitsRepresentation<P> {
     renderObjects: ReadonlyArray<RenderObject>
     create: (group: Unit.SymmetryGroup, props: P) => Task<void>
     update: (props: P) => Task<boolean>
-    getLoci: (pickingId: PickingId) => Loci | null
+    getLoci: (pickingId: PickingId) => Loci
     mark: (loci: Loci, action: MarkerAction) => void
 }
 
@@ -49,7 +49,7 @@ export function StructureRepresentation<P extends StructureProps>(reprCtor: () =
             const loc = groupReprs[i].repr.getLoci(pickingId)
             if (loc) return loc
         }
-        return null
+        return EmptyLoci
     }
 
     return {
diff --git a/src/mol-geo/representation/structure/point.ts b/src/mol-geo/representation/structure/point.ts
index a5ea8bdf6..937797308 100644
--- a/src/mol-geo/representation/structure/point.ts
+++ b/src/mol-geo/representation/structure/point.ts
@@ -19,7 +19,7 @@ import { deepEqual, defaults } from 'mol-util';
 import { SortedArray } from 'mol-data/int';
 import { RenderableState, PointValues } from 'mol-gl/renderable';
 import { PickingId } from '../../util/picking';
-import { Loci } from 'mol-model/loci';
+import { Loci, EmptyLoci } from 'mol-model/loci';
 import { MarkerAction, createMarkers } from '../../util/marker-data';
 
 export const DefaultPointProps = {
@@ -164,7 +164,7 @@ export default function PointUnitsRepresentation(): UnitsRepresentation<PointPro
                 const indices = SortedArray.ofSingleton(elementId)
                 return Element.Loci([{ unit, indices }])
             }
-            return null
+            return EmptyLoci
         },
         mark(loci: Loci, action: MarkerAction) {
             markElement(points.values.tMarker, currentGroup, loci, action)
diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts
index d93a6d00a..a80d30964 100644
--- a/src/mol-geo/representation/structure/spacefill.ts
+++ b/src/mol-geo/representation/structure/spacefill.ts
@@ -21,7 +21,7 @@ import { Mesh } from '../../shape/mesh';
 import { PickingId } from '../../util/picking';
 import { SortedArray } from 'mol-data/int';
 import { createMarkers, MarkerAction } from '../../util/marker-data';
-import { Loci } from 'mol-model/loci';
+import { Loci, EmptyLoci } from 'mol-model/loci';
 
 function createSpacefillMesh(unit: Unit, detail: number, mesh?: Mesh) {
     let radius: Element.Property<number>
@@ -152,7 +152,7 @@ export default function SpacefillUnitsRepresentation(): UnitsRepresentation<Spac
                 const indices = SortedArray.ofSingleton(elementId);
                 return Element.Loci([{ unit, indices }])
             }
-            return null
+            return EmptyLoci
         },
         mark(loci: Loci, action: MarkerAction) {
             markElement(spheres.values.tMarker, currentGroup, loci, action)
diff --git a/src/mol-geo/representation/volume/index.ts b/src/mol-geo/representation/volume/index.ts
index b3f86ff34..f0104fb99 100644
--- a/src/mol-geo/representation/volume/index.ts
+++ b/src/mol-geo/representation/volume/index.ts
@@ -9,14 +9,14 @@ import { RenderObject } from 'mol-gl/render-object';
 import { RepresentationProps, Representation } from '..';
 import { VolumeData } from 'mol-model/volume';
 import { PickingId } from '../../util/picking';
-import { Loci } from 'mol-model/loci';
+import { Loci, EmptyLoci } from 'mol-model/loci';
 import { MarkerAction } from '../../util/marker-data';
 
 export interface VolumeElementRepresentation<P> {
     renderObjects: ReadonlyArray<RenderObject>
     create: (volumeData: VolumeData, props: P) => Task<void>
     update: (props: P) => Task<boolean>
-    getLoci: (pickingId: PickingId) => Loci | null
+    getLoci: (pickingId: PickingId) => Loci
     mark: (loci: Loci, action: MarkerAction) => void
 }
 
@@ -39,7 +39,7 @@ export function VolumeRepresentation<P>(reprCtor: () => VolumeElementRepresentat
         },
         getLoci(pickingId: PickingId) {
             // TODO
-            return null
+            return EmptyLoci
         },
         mark(loci: Loci, action: MarkerAction) {
             // TODO
diff --git a/src/mol-geo/representation/volume/surface.ts b/src/mol-geo/representation/volume/surface.ts
index 0d133c89d..c22140e97 100644
--- a/src/mol-geo/representation/volume/surface.ts
+++ b/src/mol-geo/representation/volume/surface.ts
@@ -19,7 +19,7 @@ import { getMeshData } from '../../util/mesh-data';
 import { RenderableState, MeshValues } from 'mol-gl/renderable';
 import { PickingId } from '../../util/picking';
 import { createEmptyMarkers, MarkerAction } from '../../util/marker-data';
-import { Loci } from 'mol-model/loci';
+import { Loci, EmptyLoci } from 'mol-model/loci';
 
 export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValue) {
     return Task.create<Mesh>('Volume Surface', async ctx => {
@@ -109,7 +109,7 @@ export default function Surface(): VolumeElementRepresentation<SurfaceProps> {
         },
         getLoci(pickingId: PickingId) {
             // TODO
-            return null
+            return EmptyLoci
         },
         mark(loci: Loci, action: MarkerAction) {
             // TODO
diff --git a/src/mol-model/loci.ts b/src/mol-model/loci.ts
index 586ee66d3..85b9fa4de 100644
--- a/src/mol-model/loci.ts
+++ b/src/mol-model/loci.ts
@@ -14,4 +14,11 @@ export function isEveryLoci(x: any): x is EveryLoci {
     return !!x && x.kind === 'every-loci';
 }
 
-export type Loci =  Element.Loci | Link.Loci | EveryLoci
\ No newline at end of file
+/** A Loci that that is empty */
+export const EmptyLoci = { kind: 'empty-loci' as 'empty-loci' }
+export type EmptyLoci = typeof EmptyLoci
+export function isEmptyLoci(x: any): x is EmptyLoci {
+    return !!x && x.kind === 'empty-loci';
+}
+
+export type Loci =  Element.Loci | Link.Loci | EveryLoci | EmptyLoci
\ No newline at end of file
diff --git a/src/mol-view/label.ts b/src/mol-view/label.ts
index 0ea82df1b..ddb518bd6 100644
--- a/src/mol-view/label.ts
+++ b/src/mol-view/label.ts
@@ -6,7 +6,6 @@
  */
 
 import { Unit, Element, Queries } from 'mol-model/structure';
-import { Link } from 'mol-model/structure/structure/unit/links';
 import { Loci } from 'mol-model/loci';
 
 const elementLocA = Element.Location()
@@ -17,21 +16,29 @@ function setElementLocation(loc: Element.Location, unit: Unit, index: number) {
     loc.element = unit.elements[index]
 }
 
-export function labelFirst(loci: Loci) {
-    if(Element.isLoci(loci)) {
-        const e = loci.elements[0]
-        if (e && e.indices[0] !== undefined) {
-            return elementLabel(Element.Location(e.unit, e.indices[0]))
-        }
-    } else if (Link.isLoci(loci)) {
-        const bond = loci.links[0]
-        if (bond) {
-            setElementLocation(elementLocA, bond.aUnit, bond.aIndex)
-            setElementLocation(elementLocB, bond.bUnit, bond.bIndex)
-            return `${elementLabel(elementLocA)} - ${elementLabel(elementLocB)}`
-        }
+export function labelFirst(loci: Loci): string {
+    switch (loci.kind) {
+        case 'element-loci':
+            const e = loci.elements[0]
+            if (e && e.indices[0] !== undefined) {
+                return elementLabel(Element.Location(e.unit, e.indices[0]))
+            } else {
+                return 'Nothing'
+            }
+        case 'link-loci':
+            const bond = loci.links[0]
+            if (bond) {
+                setElementLocation(elementLocA, bond.aUnit, bond.aIndex)
+                setElementLocation(elementLocB, bond.bUnit, bond.bIndex)
+                return `${elementLabel(elementLocA)} - ${elementLabel(elementLocB)}`
+            } else {
+                return 'Nothing'
+            }
+        case 'every-loci':
+            return 'Evertything'
+        case 'empty-loci':
+            return 'Nothing'
     }
-    return ''
 }
 
 export function elementLabel(loc: Element.Location) {
-- 
GitLab