Browse Source

refactoring

David Sehnal 5 years ago
parent
commit
ba65e35c51

+ 1 - 1
src/mol-plugin-state/animation/manager.ts

@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { PluginComponent } from '../../mol-plugin/component';
+import { PluginComponent } from '../component';
 import { PluginContext } from '../../mol-plugin/context';
 import { PluginStateAnimation } from './model';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';

+ 1 - 1
src/mol-plugin-state/camera.ts

@@ -7,7 +7,7 @@
 import { Camera } from '../mol-canvas3d/camera';
 import { OrderedMap } from 'immutable';
 import { UUID } from '../mol-util';
-import { PluginComponent } from '../mol-plugin/component';
+import { PluginComponent } from './component';
 
 export { CameraSnapshotManager }
 

+ 0 - 0
src/mol-plugin/component.ts → src/mol-plugin-state/component.ts


+ 0 - 98
src/mol-plugin-state/manager/structure.ts

@@ -1,98 +0,0 @@
-/**
- * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { PluginContext } from '../../mol-plugin/context';
-import { StructureHierarchy, buildStructureHierarchy, ModelRef, StructureComponentRef } from './structure/hierarchy';
-import { RxEventHelper } from '../../mol-util/rx-event-helper';
-
-export class StructureHierarchyManager {
-    private ev = RxEventHelper.create();
-
-    readonly behaviors = {
-        hierarchy: this.ev.behavior(StructureHierarchy()),
-        currentModels: this.ev.behavior([] as ReadonlyArray<ModelRef>)
-    }
-
-    private checkCurrent() {
-        const hierarchy = this.behaviors.hierarchy.value;
-        const current = this.behaviors.currentModels.value;
-        if (current.length === 0) {
-            const models = hierarchy.trajectories[0]?.models;
-            if (models) {
-                this.behaviors.currentModels.next(models);
-            }
-            return;
-        }
-
-        const newCurrent: ModelRef[] = [];
-        for (const c of current) {
-            const ref = hierarchy.refs.get(c.cell.transform.ref) as ModelRef;
-            if (!ref) continue;
-            newCurrent.push(ref);
-        }
-
-        if (newCurrent.length === 0 && hierarchy.trajectories[0]?.models) {
-            this.behaviors.currentModels.next(hierarchy.trajectories[0]?.models);
-        }
-
-        this.behaviors.currentModels.next(newCurrent);
-    }
-
-    private sync() {
-        const update = buildStructureHierarchy(this.plugin.state.dataState, this.behaviors.hierarchy.value);
-        if (update.added.length === 0 && update.updated.length === 0 && update.removed.length === 0) {
-            return;
-        }
-
-        this.behaviors.hierarchy.next(update.hierarchy)
-        this.checkCurrent();
-    }
-
-    constructor(private plugin: PluginContext) {
-        plugin.state.dataState.events.changed.subscribe(e => {
-            if (e.inTransaction || plugin.behaviors.state.isAnimating.value) return;
-            this.sync();
-        });
-
-        plugin.behaviors.state.isAnimating.subscribe(isAnimating => {
-            if (!isAnimating && !plugin.behaviors.state.isUpdating.value) this.sync();
-        });
-    }
-}
-
-export namespace StructureHierarchyManager {
-    function componentKey(c: StructureComponentRef) {
-        if (!c.cell.transform.tags) return;
-        return [...c.cell.transform.tags].sort().join();
-    }
-
-    export function getCommonComponentPivots(models: ReadonlyArray<ModelRef>) {
-        if (!models[0]?.structures?.length) return [];
-        if (models[0]?.structures?.length === 1) return models[0]?.structures[0]?.components || [];
-
-        const pivots = new Map<string, StructureComponentRef>();
-
-        for (const c of models[0]?.structures[0]?.components) {
-            const key = componentKey(c);
-            if (!key) continue;
-            pivots.set(key, c);
-        }
-
-        for (const m of models) {
-            for (const s of m.structures) {
-                for (const c of s.components) {
-                    const key = componentKey(c);
-                    if (!key) continue;
-                    if (!pivots.has(key)) pivots.delete(key);
-                }
-            }
-        }
-
-        const ret: StructureComponentRef[] = [];
-        pivots.forEach(function (this: StructureComponentRef[], p) { this.push(p) }, ret);
-        return ret;
-    }
-}

+ 210 - 0
src/mol-plugin-state/manager/structure/hierarchy-state.ts

@@ -0,0 +1,210 @@
+/**
+ * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author David Sehnal <david.sehnal@gmail.com>
+ */
+
+import { PluginStateObject as SO } from '../../objects';
+import { StateObject, StateTransform, State, StateObjectCell, StateTree } from '../../../mol-state';
+import { StructureBuilderTags } from '../../builder/structure';
+import { RepresentationProviderTags } from '../../builder/structure/provider';
+
+export function buildStructureHierarchy(state: State, previous?: StructureHierarchy) {
+    const build = BuildState(state, previous || StructureHierarchy());
+    StateTree.doPreOrder(state.tree, state.tree.root, build, visitCell);
+    if (previous) previous.refs.forEach(isRemoved, build);
+    return { hierarchy: build.hierarchy, added: build.added, updated: build.updated, removed: build.removed };
+}
+
+export interface StructureHierarchy {
+    trajectories: TrajectoryRef[],
+    refs: Map<StateTransform.Ref, HierarchyRef>
+}
+
+export function StructureHierarchy(): StructureHierarchy {
+    return { trajectories: [], refs: new Map() }
+}
+
+interface RefBase<K extends string = string, T extends StateObject = StateObject> {
+    kind: K,
+    cell: StateObjectCell<T>,
+    version: StateTransform['version']
+}
+
+export type HierarchyRef = 
+    | TrajectoryRef
+    | ModelRef | ModelPropertiesRef
+    | StructureRef | StructurePropertiesRef | StructureComponentRef | StructureRepresentationRef
+
+export interface TrajectoryRef extends RefBase<'trajectory', SO.Molecule.Trajectory> {
+    models: ModelRef[]
+}
+
+function TrajectoryRef(cell: StateObjectCell<SO.Molecule.Trajectory>): TrajectoryRef { 
+    return { kind: 'trajectory', cell, version: cell.transform.version, models: [] };
+}
+
+export interface ModelRef extends RefBase<'model', SO.Molecule.Model> {
+    trajectory: TrajectoryRef,
+    properties?: ModelPropertiesRef,
+    structures: StructureRef[]
+}
+
+function ModelRef(cell: StateObjectCell<SO.Molecule.Model>, trajectory: TrajectoryRef): ModelRef {
+    return { kind: 'model', cell, version: cell.transform.version, trajectory, structures: [] };
+}
+
+export interface ModelPropertiesRef extends RefBase<'model-properties', SO.Molecule.Model> {
+    model: ModelRef
+}
+
+function ModelPropertiesRef(cell: StateObjectCell<SO.Molecule.Model>, model: ModelRef): ModelPropertiesRef {
+    return { kind: 'model-properties', cell, version: cell.transform.version, model };
+}
+
+export interface StructureRef extends RefBase<'structure', SO.Molecule.Structure> {
+    model: ModelRef,
+    properties?: StructurePropertiesRef,
+    components: StructureComponentRef[],
+    // representations: StructureRepresentationRef[],
+    currentFocus?: {
+        focus?: StructureComponentRef,
+        surroundings?: StructureComponentRef,
+    },
+    // volumeStreaming?: ....
+}
+
+function StructureRef(cell: StateObjectCell<SO.Molecule.Structure>, model: ModelRef): StructureRef {
+    return { kind: 'structure', cell, version: cell.transform.version, model, components: [] };
+}
+
+export interface StructurePropertiesRef extends RefBase<'structure-properties', SO.Molecule.Structure> {
+    structure: StructureRef
+}
+
+function StructurePropertiesRef(cell: StateObjectCell<SO.Molecule.Structure>, structure: StructureRef): StructurePropertiesRef {
+    return { kind: 'structure-properties', cell, version: cell.transform.version, structure };
+}
+
+export interface StructureComponentRef extends RefBase<'structure-component', SO.Molecule.Structure> {
+    structure: StructureRef,
+    representations: StructureRepresentationRef[],
+}
+
+function StructureComponentRef(cell: StateObjectCell<SO.Molecule.Structure>, structure: StructureRef): StructureComponentRef {
+    return { kind: 'structure-component', cell, version: cell.transform.version, structure, representations: [] };
+}
+
+export interface StructureRepresentationRef extends RefBase<'structure-representation', SO.Molecule.Structure.Representation3D> {
+    component: StructureComponentRef
+}
+
+function StructureRepresentationRef(cell: StateObjectCell<SO.Molecule.Structure.Representation3D>, component: StructureComponentRef): StructureRepresentationRef {
+    return { kind: 'structure-representation', cell, version: cell.transform.version, component };
+}
+
+interface BuildState {
+    state: State,
+    oldHierarchy: StructureHierarchy,
+
+    hierarchy: StructureHierarchy,
+
+    currentTrajectory?: TrajectoryRef,
+    currentModel?: ModelRef,
+    currentStructure?: StructureRef,
+    currentComponent?: StructureComponentRef,
+
+    updated: HierarchyRef[],
+    added: HierarchyRef[],
+    removed: HierarchyRef[]
+}
+
+function BuildState(state: State, oldHierarchy: StructureHierarchy): BuildState {
+    return { state, oldHierarchy, hierarchy: StructureHierarchy(), updated: [], added: [], removed: [] };
+}
+
+function createOrUpdateRefList<R extends HierarchyRef, C extends any[]>(state: BuildState, cell: StateObjectCell, list: R[], ctor: (...args: C) => R, ...args: C) {
+    const ref: R = ctor(...args);
+    list.push(ref);
+    state.hierarchy.refs.set(cell.transform.ref, ref);
+    const old = state.oldHierarchy.refs.get(cell.transform.ref);
+    if (old) {
+        if (old.version !== cell.transform.version) state.updated.push(ref);
+    } else {
+        state.added.push(ref);
+    }
+    return ref;
+}
+
+function createOrUpdateRef<R extends HierarchyRef, C extends any[]>(state: BuildState, cell: StateObjectCell, old: R | undefined, ctor: (...args: C) => R, ...args: C) {
+    const ref: R = ctor(...args);
+    state.hierarchy.refs.set(cell.transform.ref, ref);
+    if (old) {
+        if (old.version !== cell.transform.version) state.updated.push(ref);
+    } else {
+        state.added.push(ref);
+    }
+    return ref;
+}
+
+const tagMap: [string, (state: BuildState, cell: StateObjectCell) => boolean | void][] = [
+    [StructureBuilderTags.Trajectory, (state, cell) => {
+        state.currentTrajectory = createOrUpdateRefList(state, cell, state.hierarchy.trajectories, TrajectoryRef, cell);
+    }],
+    [StructureBuilderTags.Model, (state, cell) => {
+        if (!state.currentTrajectory) return false;
+        state.currentModel = createOrUpdateRefList(state, cell, state.currentTrajectory.models, ModelRef, cell, state.currentTrajectory);
+    }],
+    [StructureBuilderTags.ModelProperties, (state, cell) => {
+        if (!state.currentModel) return false;
+        state.currentModel.properties = createOrUpdateRef(state, cell, state.currentModel.properties, ModelPropertiesRef, cell, state.currentModel);
+    }],
+    [StructureBuilderTags.Structure, (state, cell) => {
+        if (!state.currentModel) return false;
+        state.currentStructure = createOrUpdateRefList(state, cell, state.currentModel.structures, StructureRef, cell, state.currentModel);
+    }],
+    [StructureBuilderTags.StructureProperties, (state, cell) => {
+        if (!state.currentStructure) return false;
+        state.currentStructure.properties = createOrUpdateRef(state, cell, state.currentStructure.properties, StructurePropertiesRef, cell, state.currentStructure);
+    }],
+    [StructureBuilderTags.Component, (state, cell) => {
+        if (!state.currentStructure) return false;
+        state.currentComponent = createOrUpdateRefList(state, cell, state.currentStructure.components, StructureComponentRef, cell, state.currentStructure);
+    }],
+    [RepresentationProviderTags.Representation, (state, cell) => {
+        if (!state.currentComponent) return false;
+        createOrUpdateRefList(state, cell, state.currentComponent.representations, StructureRepresentationRef, cell, state.currentComponent);
+    }]
+]
+
+function isValidCell(cell?: StateObjectCell): cell is StateObjectCell {
+    if (!cell || !cell.parent.cells.has(cell.transform.ref)) return false;
+    const { obj } = cell;
+    if (!obj || obj === StateObject.Null || (cell.status !== 'ok' && cell.status !== 'error')) return false;
+    return true;
+}
+
+function visitCell(t: StateTransform, tree: StateTree, state: BuildState): boolean {
+    const cell = state.state.cells.get(t.ref);
+    if (!isValidCell(cell)) return false;
+
+    for (const [t, f] of tagMap) {
+        if (StateObject.hasTag(cell.obj!, t)) {
+            const stop = f(state, cell);
+            if (stop === false) return false;
+            return true;
+        }
+    }
+
+    if (state.currentComponent && SO.Molecule.Structure.Representation3D.is(cell.obj)) {
+        createOrUpdateRefList(state, cell, state.currentComponent.representations, StructureRepresentationRef, cell, state.currentComponent);
+    }
+
+    return true;
+}
+
+function isRemoved(this: BuildState, ref: HierarchyRef) {
+    const { cell } = ref;
+    if (isValidCell(cell)) return;
+    this.removed.push(ref);
+}

+ 80 - 181
src/mol-plugin-state/manager/structure/hierarchy.ts

@@ -4,207 +4,106 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { PluginStateObject as SO } from '../../objects';
-import { StateObject, StateTransform, State, StateObjectCell, StateTree } from '../../../mol-state';
-import { StructureBuilderTags } from '../../builder/structure';
-import { RepresentationProviderTags } from '../../builder/structure/provider';
-
-export function buildStructureHierarchy(state: State, previous?: StructureHierarchy) {
-    const build = BuildState(state, previous || StructureHierarchy());
-    StateTree.doPreOrder(state.tree, state.tree.root, build, visitCell);
-    if (previous) previous.refs.forEach(isRemoved, build);
-    return { hierarchy: build.hierarchy, added: build.added, updated: build.updated, removed: build.removed };
-}
-
-export interface StructureHierarchy {
-    trajectories: TrajectoryRef[],
-    refs: Map<StateTransform.Ref, HierarchyRef>
-}
-
-export function StructureHierarchy(): StructureHierarchy {
-    return { trajectories: [], refs: new Map() }
-}
-
-interface RefBase<K extends string = string, T extends StateObject = StateObject> {
-    kind: K,
-    cell: StateObjectCell<T>,
-    version: StateTransform['version']
-}
+import { PluginContext } from '../../../mol-plugin/context';
+import { StructureHierarchy, buildStructureHierarchy, ModelRef, StructureComponentRef } from './hierarchy-state';
+import { PluginComponent } from '../../component';
 
-export type HierarchyRef = 
-    | TrajectoryRef
-    | ModelRef | ModelPropertiesRef
-    | StructureRef | StructurePropertiesRef | StructureComponentRef | StructureRepresentationRef
-
-export interface TrajectoryRef extends RefBase<'trajectory', SO.Molecule.Trajectory> {
-    models: ModelRef[]
-}
-
-function TrajectoryRef(cell: StateObjectCell<SO.Molecule.Trajectory>): TrajectoryRef { 
-    return { kind: 'trajectory', cell, version: cell.transform.version, models: [] };
-}
-
-export interface ModelRef extends RefBase<'model', SO.Molecule.Model> {
-    trajectory: TrajectoryRef,
-    properties?: ModelPropertiesRef,
-    structures: StructureRef[]
-}
-
-function ModelRef(cell: StateObjectCell<SO.Molecule.Model>, trajectory: TrajectoryRef): ModelRef {
-    return { kind: 'model', cell, version: cell.transform.version, trajectory, structures: [] };
-}
-
-export interface ModelPropertiesRef extends RefBase<'model-properties', SO.Molecule.Model> {
-    model: ModelRef
-}
-
-function ModelPropertiesRef(cell: StateObjectCell<SO.Molecule.Model>, model: ModelRef): ModelPropertiesRef {
-    return { kind: 'model-properties', cell, version: cell.transform.version, model };
-}
-
-export interface StructureRef extends RefBase<'structure', SO.Molecule.Structure> {
-    model: ModelRef,
-    properties?: StructurePropertiesRef,
-    components: StructureComponentRef[],
-    // representations: StructureRepresentationRef[],
-    currentFocus?: {
-        focus?: StructureComponentRef,
-        surroundings?: StructureComponentRef,
-    },
-    // volumeStreaming?: ....
-}
-
-function StructureRef(cell: StateObjectCell<SO.Molecule.Structure>, model: ModelRef): StructureRef {
-    return { kind: 'structure', cell, version: cell.transform.version, model, components: [] };
-}
-
-export interface StructurePropertiesRef extends RefBase<'structure-properties', SO.Molecule.Structure> {
-    structure: StructureRef
+interface StructureHierarchyManagerState {
+    hierarchy: StructureHierarchy,
+    currentModels: ReadonlyArray<ModelRef>,
 }
 
-function StructurePropertiesRef(cell: StateObjectCell<SO.Molecule.Structure>, structure: StructureRef): StructurePropertiesRef {
-    return { kind: 'structure-properties', cell, version: cell.transform.version, structure };
-}
+export class StructureHierarchyManager extends PluginComponent<StructureHierarchyManagerState> {
+    readonly behaviors = {
+        hierarchy: this.ev.behavior(this.state.hierarchy),
+        currentModels: this.ev.behavior(this.state.currentModels)
+    }
 
-export interface StructureComponentRef extends RefBase<'structure-component', SO.Molecule.Structure> {
-    structure: StructureRef,
-    representations: StructureRepresentationRef[],
-}
+    private syncCurrent() {
+        const hierarchy = this.behaviors.hierarchy.value;
+        const current = this.behaviors.currentModels.value;
+        if (current.length === 0) {
+            const models = hierarchy.trajectories[0]?.models;
+            if (models) {
+                return models;
+            }
+            return [];
+        }
 
-function StructureComponentRef(cell: StateObjectCell<SO.Molecule.Structure>, structure: StructureRef): StructureComponentRef {
-    return { kind: 'structure-component', cell, version: cell.transform.version, structure, representations: [] };
-}
+        const newCurrent: ModelRef[] = [];
+        for (const c of current) {
+            const ref = hierarchy.refs.get(c.cell.transform.ref) as ModelRef;
+            if (!ref) continue;
+            newCurrent.push(ref);
+        }
 
-export interface StructureRepresentationRef extends RefBase<'structure-representation', SO.Molecule.Structure.Representation3D> {
-    component: StructureComponentRef
-}
+        if (newCurrent.length === 0 && hierarchy.trajectories[0]?.models) {
+            return hierarchy.trajectories[0]?.models;
+        }
 
-function StructureRepresentationRef(cell: StateObjectCell<SO.Molecule.Structure.Representation3D>, component: StructureComponentRef): StructureRepresentationRef {
-    return { kind: 'structure-representation', cell, version: cell.transform.version, component };
-}
+        return newCurrent;
+    }
 
-interface BuildState {
-    state: State,
-    oldHierarchy: StructureHierarchy,
+    private sync() {
+        const update = buildStructureHierarchy(this.plugin.state.dataState, this.behaviors.hierarchy.value);
+        if (update.added.length === 0 && update.updated.length === 0 && update.removed.length === 0) {
+            return;
+        }
 
-    hierarchy: StructureHierarchy,
+        const currentModels = this.syncCurrent();
+        this.updateState({ hierarchy: update.hierarchy, currentModels });
 
-    currentTrajectory?: TrajectoryRef,
-    currentModel?: ModelRef,
-    currentStructure?: StructureRef,
-    currentComponent?: StructureComponentRef,
+        this.behaviors.hierarchy.next(this.state.hierarchy)
+        this.behaviors.currentModels.next(this.state.currentModels);
+    }
 
-    updated: HierarchyRef[],
-    added: HierarchyRef[],
-    removed: HierarchyRef[]
-}
+    constructor(private plugin: PluginContext) {
+        super({
+            hierarchy: StructureHierarchy(),
+            currentModels: []
+        });
 
-function BuildState(state: State, oldHierarchy: StructureHierarchy): BuildState {
-    return { state, oldHierarchy, hierarchy: StructureHierarchy(), updated: [], added: [], removed: [] };
-}
+        plugin.state.dataState.events.changed.subscribe(e => {
+            if (e.inTransaction || plugin.behaviors.state.isAnimating.value) return;
+            this.sync();
+        });
 
-function createOrUpdateRefList<R extends HierarchyRef, C extends any[]>(state: BuildState, cell: StateObjectCell, list: R[], ctor: (...args: C) => R, ...args: C) {
-    const ref: R = ctor(...args);
-    list.push(ref);
-    state.hierarchy.refs.set(cell.transform.ref, ref);
-    const old = state.oldHierarchy.refs.get(cell.transform.ref);
-    if (old) {
-        if (old.version !== cell.transform.version) state.updated.push(ref);
-    } else {
-        state.added.push(ref);
+        plugin.behaviors.state.isAnimating.subscribe(isAnimating => {
+            if (!isAnimating && !plugin.behaviors.state.isUpdating.value) this.sync();
+        });
     }
-    return ref;
 }
 
-function createOrUpdateRef<R extends HierarchyRef, C extends any[]>(state: BuildState, cell: StateObjectCell, old: R | undefined, ctor: (...args: C) => R, ...args: C) {
-    const ref: R = ctor(...args);
-    state.hierarchy.refs.set(cell.transform.ref, ref);
-    if (old) {
-        if (old.version !== cell.transform.version) state.updated.push(ref);
-    } else {
-        state.added.push(ref);
+export namespace StructureHierarchyManager {
+    function componentKey(c: StructureComponentRef) {
+        if (!c.cell.transform.tags) return;
+        return [...c.cell.transform.tags].sort().join();
     }
-    return ref;
-}
 
-const tagMap: [string, (state: BuildState, cell: StateObjectCell) => boolean | void][] = [
-    [StructureBuilderTags.Trajectory, (state, cell) => {
-        state.currentTrajectory = createOrUpdateRefList(state, cell, state.hierarchy.trajectories, TrajectoryRef, cell);
-    }],
-    [StructureBuilderTags.Model, (state, cell) => {
-        if (!state.currentTrajectory) return false;
-        state.currentModel = createOrUpdateRefList(state, cell, state.currentTrajectory.models, ModelRef, cell, state.currentTrajectory);
-    }],
-    [StructureBuilderTags.ModelProperties, (state, cell) => {
-        if (!state.currentModel) return false;
-        state.currentModel.properties = createOrUpdateRef(state, cell, state.currentModel.properties, ModelPropertiesRef, cell, state.currentModel);
-    }],
-    [StructureBuilderTags.Structure, (state, cell) => {
-        if (!state.currentModel) return false;
-        state.currentStructure = createOrUpdateRefList(state, cell, state.currentModel.structures, StructureRef, cell, state.currentModel);
-    }],
-    [StructureBuilderTags.StructureProperties, (state, cell) => {
-        if (!state.currentStructure) return false;
-        state.currentStructure.properties = createOrUpdateRef(state, cell, state.currentStructure.properties, StructurePropertiesRef, cell, state.currentStructure);
-    }],
-    [StructureBuilderTags.Component, (state, cell) => {
-        if (!state.currentStructure) return false;
-        state.currentComponent = createOrUpdateRefList(state, cell, state.currentStructure.components, StructureComponentRef, cell, state.currentStructure);
-    }],
-    [RepresentationProviderTags.Representation, (state, cell) => {
-        if (!state.currentComponent) return false;
-        createOrUpdateRefList(state, cell, state.currentComponent.representations, StructureRepresentationRef, cell, state.currentComponent);
-    }]
-]
-
-function isValidCell(cell?: StateObjectCell): cell is StateObjectCell {
-    if (!cell || !cell.parent.cells.has(cell.transform.ref)) return false;
-    const { obj } = cell;
-    if (!obj || obj === StateObject.Null || (cell.status !== 'ok' && cell.status !== 'error')) return false;
-    return true;
-}
+    export function getCommonComponentPivots(models: ReadonlyArray<ModelRef>) {
+        if (!models[0]?.structures?.length) return [];
+        if (models[0]?.structures?.length === 1) return models[0]?.structures[0]?.components || [];
 
-function visitCell(t: StateTransform, tree: StateTree, state: BuildState): boolean {
-    const cell = state.state.cells.get(t.ref);
-    if (!isValidCell(cell)) return false;
+        const pivots = new Map<string, StructureComponentRef>();
 
-    for (const [t, f] of tagMap) {
-        if (StateObject.hasTag(cell.obj!, t)) {
-            const stop = f(state, cell);
-            if (stop === false) return false;
-            return true;
+        for (const c of models[0]?.structures[0]?.components) {
+            const key = componentKey(c);
+            if (!key) continue;
+            pivots.set(key, c);
         }
-    }
 
-    if (state.currentComponent && SO.Molecule.Structure.Representation3D.is(cell.obj)) {
-        createOrUpdateRefList(state, cell, state.currentComponent.representations, StructureRepresentationRef, cell, state.currentComponent);
-    }
-
-    return true;
-}
+        for (const m of models) {
+            for (const s of m.structures) {
+                for (const c of s.components) {
+                    const key = componentKey(c);
+                    if (!key) continue;
+                    if (!pivots.has(key)) pivots.delete(key);
+                }
+            }
+        }
 
-function isRemoved(this: BuildState, ref: HierarchyRef) {
-    const { cell } = ref;
-    if (isValidCell(cell)) return;
-    this.removed.push(ref);
-}
+        const ret: StructureComponentRef[] = [];
+        pivots.forEach(function (this: StructureComponentRef[], p) { this.push(p) }, ret);
+        return ret;
+    }
+}

+ 1 - 1
src/mol-plugin-state/manager/structure/measurement.ts

@@ -11,7 +11,7 @@ import { StateTransforms } from '../../transforms';
 import { PluginCommands } from '../../../mol-plugin/commands';
 import { arraySetAdd } from '../../../mol-util/array';
 import { PluginStateObject } from '../../objects';
-import { PluginComponent } from '../../../mol-plugin/component';
+import { PluginComponent } from '../../component';
 import { ParamDefinition as PD } from '../../../mol-util/param-definition';
 import { MeasurementRepresentationCommonTextParams } from '../../../mol-repr/shape/loci/common';
 

+ 1 - 1
src/mol-plugin-state/snapshots.ts

@@ -7,7 +7,7 @@
 import { List } from 'immutable';
 import { UUID } from '../mol-util';
 import { PluginState } from '../mol-plugin/state';
-import { PluginComponent } from '../mol-plugin/component';
+import { PluginComponent } from './component';
 import { PluginContext } from '../mol-plugin/context';
 
 export { PluginStateSnapshotManager }

+ 2 - 2
src/mol-plugin-ui/structure/components.tsx

@@ -6,8 +6,8 @@
 
 import * as React from 'react';
 import { CollapsableControls, CollapsableState, PurePluginUIComponent } from '../base';
-import { StructureHierarchyManager } from '../../mol-plugin-state/manager/structure';
-import { StructureComponentRef, StructureRepresentationRef } from '../../mol-plugin-state/manager/structure/hierarchy';
+import { StructureHierarchyManager } from '../../mol-plugin-state/manager/structure/hierarchy';
+import { StructureComponentRef, StructureRepresentationRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
 import { State, StateAction } from '../../mol-state';
 import { PluginCommands } from '../../mol-plugin/commands';
 import { ExpandGroup, IconButton, ControlGroup } from '../controls/common';

+ 1 - 1
src/mol-plugin/context.ts

@@ -48,7 +48,7 @@ import { CustomProperty } from '../mol-model-props/common/custom-property';
 import { PluginConfigManager } from './config';
 import { DataBuilder } from '../mol-plugin-state/builder/data';
 import { StructureBuilder } from '../mol-plugin-state/builder/structure';
-import { StructureHierarchyManager } from '../mol-plugin-state/manager/structure';
+import { StructureHierarchyManager } from '../mol-plugin-state/manager/structure/hierarchy';
 
 export class PluginContext {
     private disposed = false;

+ 1 - 1
src/mol-plugin/layout.ts

@@ -6,7 +6,7 @@
  */
 
 import { ParamDefinition as PD } from '../mol-util/param-definition';
-import { PluginComponent } from './component';
+import { PluginComponent } from '../mol-plugin-state/component';
 import { PluginContext } from './context';
 import { PluginCommands } from './commands';
 

+ 1 - 1
src/mol-plugin/util/toast.ts

@@ -6,7 +6,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { PluginComponent } from '../component';
+import { PluginComponent } from '../../mol-plugin-state/component';
 import { OrderedMap } from 'immutable';
 import { PluginContext } from '../context';
 import { PluginCommands } from '../commands';