/** * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose */ import * as React from 'react'; import { CollapsableControls, CollapsableState } from '../base'; import { StructureSelectionQueries, SelectionModifier } from '../../util/structure-selection-helper'; import { ButtonSelect, Options } from '../controls/common'; import { PluginCommands } from '../../command'; import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { Interactivity } from '../../util/interactivity'; import { ParameterControls } from '../controls/parameters'; import { stripTags } from '../../../mol-util/string'; import { StructureElement } from '../../../mol-model/structure'; const SSQ = StructureSelectionQueries const DefaultQueries: (keyof typeof SSQ)[] = [ 'all', 'polymer', 'trace', 'protein', 'nucleic', 'water', 'branched', 'ligand', 'nonStandardPolymer', 'surroundings', 'complement', 'bonded' ] const StructureSelectionParams = { granularity: Interactivity.Params.granularity, } interface StructureSelectionControlsState extends CollapsableState { minRadius: number, extraRadius: number, durationMs: number, isDisabled: boolean } export class StructureSelectionControls extends CollapsableControls { componentDidMount() { this.subscribe(this.plugin.events.interactivity.selectionUpdated, () => { this.forceUpdate() }); this.subscribe(this.plugin.events.interactivity.propsUpdated, () => { this.forceUpdate() }); this.subscribe(this.plugin.state.dataState.events.isUpdating, v => this.setState({ isDisabled: v })) } get stats() { const stats = this.plugin.helpers.structureSelectionManager.stats if (stats.structureCount === 0 || stats.elementCount === 0) { return 'Selected nothing' } else { return `Selected ${stripTags(stats.label)}` } } focus = () => { const { extraRadius, minRadius, durationMs } = this.state if (this.plugin.helpers.structureSelectionManager.stats.elementCount === 0) return const principalAxes = this.plugin.helpers.structureSelectionManager.getPrincipalAxes(); const { origin, dirA, dirC } = principalAxes.boxAxes const { sphere } = this.plugin.helpers.structureSelectionManager.getBoundary() const radius = Math.max(sphere.radius + extraRadius, minRadius); this.plugin.canvas3d?.camera.focus(origin, radius, durationMs, dirA, dirC); } focusLoci(loci: StructureElement.Loci) { return () => { const { extraRadius, minRadius, durationMs } = this.state if (this.plugin.helpers.structureSelectionManager.stats.elementCount === 0) return const { sphere } = StructureElement.Loci.getBoundary(loci) const radius = Math.max(sphere.radius + extraRadius, minRadius); this.plugin.canvas3d?.camera.focus(sphere.center, radius, durationMs); } } measureDistance = () => { const loci = this.plugin.helpers.structureSelectionManager.latestLoci; this.plugin.helpers.measurement.addDistance(loci[0].loci, loci[1].loci); } measureAngle = () => { const loci = this.plugin.helpers.structureSelectionManager.latestLoci; this.plugin.helpers.measurement.addAngle(loci[0].loci, loci[1].loci, loci[2].loci); } setProps = (p: { param: PD.Base, name: string, value: any }) => { if (p.name === 'granularity') { PluginCommands.Interactivity.SetProps.dispatch(this.plugin, { props: { granularity: p.value } }); } } get values () { return { granularity: this.plugin.interactivity.props.granularity, } } set = (modifier: SelectionModifier, value: string) => { const query = SSQ[value as keyof typeof SSQ] this.plugin.helpers.structureSelection.set(modifier, query.query, false) } add = (value: string) => this.set('add', value) remove = (value: string) => this.set('remove', value) only = (value: string) => this.set('only', value) queries = Options(Object.keys(StructureSelectionQueries) .map(name => [name, SSQ[name as keyof typeof SSQ].label] as [string, string]) .filter(pair => DefaultQueries.includes(pair[0] as keyof typeof SSQ))); controls =
{this.queries} {this.queries} {this.queries}
defaultState() { return { isCollapsed: false, header: 'Selection', minRadius: 8, extraRadius: 4, durationMs: 250, isDisabled: false } as S } renderControls() { const latest: JSX.Element[] = []; const mng = this.plugin.helpers.structureSelectionManager; // TODO: fix the styles, move them to CSS for (let i = 0, _i = Math.min(3, mng.latestLoci.length); i < _i; i++) { const e = mng.latestLoci[i]; latest.push(
  • {/*
    {}} />
    */}
  • ) } return
    {this.controls} { latest.length > 0 && <>
    Latest Selections & Measurement
      {latest}
    {latest.length >= 2 &&
    } {latest.length >= 3 &&
    } }
    } }