Skip to content
Snippets Groups Projects
Commit 3d4f40f6 authored by David Sehnal's avatar David Sehnal
Browse files

mol-plugin: SubstructureParentHelper

parent a51f3e7f
No related branches found
No related tags found
No related merge requests found
......@@ -24,7 +24,7 @@ export const HighlightLoci = PluginBehavior.create({
ctor: class extends PluginBehavior.Handler {
register(): void {
let prev: Representation.Loci = { loci: EmptyLoci, repr: void 0 };
const sel = this.ctx.selection.structure;
const sel = this.ctx.helpers.structureSelection;
this.subscribeObservable(this.ctx.events.canvas3d.highlight, ({ current, modifiers }) => {
if (!this.ctx.canvas3d) return;
......@@ -58,7 +58,7 @@ export const SelectLoci = PluginBehavior.create({
category: 'interaction',
ctor: class extends PluginBehavior.Handler {
register(): void {
const sel = this.ctx.selection.structure;
const sel = this.ctx.helpers.structureSelection;
const toggleSel = (current: Representation.Loci<StructureElement.Loci>) => {
if (sel.has(current.loci)) {
......
......@@ -31,6 +31,7 @@ import { LociLabelEntry, LociLabelManager } from './util/loci-label-manager';
import { TaskManager } from './util/task-manager';
import { PLUGIN_VERSION, PLUGIN_VERSION_DATE } from './version';
import { StructureElementSelectionManager } from './util/structure-element-selection';
import { SubstructureParentHelper } from './util/substructure-parent-helper';
export class PluginContext {
private disposed = false;
......@@ -99,8 +100,9 @@ export class PluginContext {
readonly customModelProperties = new CustomPropertyRegistry();
readonly customParamEditors = new Map<string, StateTransformParameters.Class>();
readonly selection = {
structure: new StructureElementSelectionManager(this)
readonly helpers = {
structureSelection: new StructureElementSelectionManager(this),
substructureParent: new SubstructureParentHelper(this)
};
initViewer(canvas: HTMLCanvasElement, container: HTMLDivElement) {
......
......@@ -4,34 +4,29 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { OrderedSet } from 'mol-data/int';
import { EmptyLoci, Loci } from 'mol-model/loci';
import { Structure, StructureElement } from 'mol-model/structure';
import { State, StateObject, StateSelection } from 'mol-state';
import { StateObject } from 'mol-state';
import { PluginContext } from '../context';
import { PluginStateObject } from '../state/objects';
import { OrderedSet } from 'mol-data/int';
export { StructureElementSelectionManager };
class StructureElementSelectionManager {
private entries = new Map<string, SelectionEntry>();
// maps structure to a parent StateObjectCell
private mapping = {
root: new Map<Structure, string>(),
tracked: new Map<string, Structure>()
};
private getEntry(s: Structure) {
if (!this.mapping.root.has(s)) return;
const key = this.mapping.root.get(s)!;
if (!this.entries.has(key)) {
const cell = this.plugin.helpers.substructureParent.get(s);
if (!cell) return;
const ref = cell.transform.ref;
if (!this.entries.has(ref)) {
const entry = SelectionEntry(s);
this.entries.set(key, entry);
this.entries.set(ref, entry);
return entry;
}
return this.entries.get(key)!;
return this.entries.get(ref)!;
}
add(loci: StructureElement.Loci): Loci {
......@@ -112,27 +107,11 @@ class StructureElementSelectionManager {
return ret || EmptyLoci;
}
private addMapping(state: State, ref: string, obj: StateObject) {
if (!PluginStateObject.Molecule.Structure.is(obj)) return;
const parent = state.select(StateSelection.Generators.byRef(ref).rootOfType([PluginStateObject.Molecule.Structure]))[0];
this.mapping.tracked.set(ref, obj.data);
if (!parent) {
this.mapping.root.set(obj.data, ref);
} else {
this.mapping.root.set(obj.data, parent.transform.ref);
}
}
private removeMapping(ref: string) {
if (!this.mapping.tracked.has(ref)) return;
const s = this.mapping.tracked.get(ref)!;
this.mapping.tracked.delete(ref);
const root = this.mapping.root.get(s);
this.mapping.root.delete(s);
if (root === ref) this.entries.delete(ref);
private onRemove(ref: string) {
if (this.entries.has(ref)) this.entries.delete(ref);
}
private updateMapping(state: State, ref: string, oldObj: StateObject | undefined, obj: StateObject) {
private onUpdate(ref: string, oldObj: StateObject | undefined, obj: StateObject) {
if (!PluginStateObject.Molecule.Structure.is(obj)) return;
if (this.entries.has(ref)) {
......@@ -146,24 +125,12 @@ class StructureElementSelectionManager {
// clear the selection
this.entries.set(ref, SelectionEntry(obj.data));
} else {
this.removeMapping(ref);
this.addMapping(state, ref, obj);
}
}
constructor(plugin: PluginContext) {
plugin.state.dataState.events.object.created.subscribe(e => {
this.addMapping(e.state, e.ref, e.obj);
});
plugin.state.dataState.events.object.removed.subscribe(e => {
this.removeMapping(e.ref);
});
plugin.state.dataState.events.object.updated.subscribe(e => {
this.updateMapping(e.state, e.ref, e.oldObj, e.obj);
});
constructor(private plugin: PluginContext) {
plugin.state.dataState.events.object.removed.subscribe(e => this.onRemove(e.ref));
plugin.state.dataState.events.object.updated.subscribe(e => this.onUpdate(e.ref, e.oldObj, e.obj));
}
}
......
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Structure } from 'mol-model/structure';
import { State, StateObject, StateSelection, StateObjectCell } from 'mol-state';
import { PluginContext } from '../context';
import { PluginStateObject } from '../state/objects';
export { SubstructureParentHelper };
class SubstructureParentHelper {
private root = new Map<Structure, string>();
private tracked = new Map<string, Structure>();
get(s: Structure): StateObjectCell<PluginStateObject.Molecule.Structure> | undefined {
const r = this.root.get(s);
if (!r) return;
return this.plugin.state.dataState.cells.get(r);
}
private addMapping(state: State, ref: string, obj: StateObject) {
if (!PluginStateObject.Molecule.Structure.is(obj)) return;
const parent = state.select(StateSelection.Generators.byRef(ref).rootOfType([PluginStateObject.Molecule.Structure]))[0];
this.tracked.set(ref, obj.data);
if (!parent) {
this.root.set(obj.data, ref);
} else {
this.root.set(obj.data, parent.transform.ref);
}
}
private removeMapping(ref: string) {
if (!this.tracked.has(ref)) return;
const s = this.tracked.get(ref)!;
this.tracked.delete(ref);
this.root.get(s);
this.root.delete(s);
}
private updateMapping(state: State, ref: string, oldObj: StateObject | undefined, obj: StateObject) {
if (!PluginStateObject.Molecule.Structure.is(obj)) return;
this.removeMapping(ref);
this.addMapping(state, ref, obj);
}
constructor(private plugin: PluginContext) {
plugin.state.dataState.events.object.created.subscribe(e => {
this.addMapping(e.state, e.ref, e.obj);
});
plugin.state.dataState.events.object.removed.subscribe(e => {
this.removeMapping(e.ref);
});
plugin.state.dataState.events.object.updated.subscribe(e => {
this.updateMapping(e.state, e.ref, e.oldObj, e.obj);
});
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment