diff --git a/src/mol-geo/representation/index.ts b/src/mol-geo/representation/index.ts index 4ef62c6952ebfa3de9fb80edd5fb4111fc49ec7d..0f0e04bf4d2ffe42f775eaa07d542f1d55bb23b1 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 492731141fe21febd63d55f474b82e5d77985818..69ac5791127e0be2d94d17e7fdebd3445e4ce8b5 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 756fc6eceeff37779ba932c54315e3dd5f168bce..4716fc2c4c123884a5d4e6c5104ea5845f81a30f 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 a5ea8bdf66ee987ac079dee5a89f601a1c4034c6..9377973081a46f5f19adb1df1b0bbd987f56805c 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 d93a6d00a5fd1b1ebbed4911452bdd6c3520cbd2..a80d30964afe9cbc6ee714ccf02417eaa27e5a90 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 b3f86ff34a0b4a3cc459c6f2f9cc2800d8c97cce..f0104fb993ac65d304b37348c47ad6bf112ce6a2 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 0d133c89d65beeff58c5a3b4f484b60b8377f979..c22140e978539e47eb184cad7d5576e944251a31 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 586ee66d308c5835340cb233bcfa78125f32487b..85b9fa4deae88a448ffcd192b2d2b52faad27a55 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 0ea82df1ba0a07c339d76453580f942cf19a85cd..ddb518bd654858148307eaa74e8e92da40ff43c4 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) {