diff --git a/src/mol-plugin/ui/controls.tsx b/src/mol-plugin/ui/controls.tsx index d8c2af001dfbc11cd1f4748b4f4d03490b5ed6e7..31c64b94e133d76048cf17aed55e7694e8b4510e 100644 --- a/src/mol-plugin/ui/controls.tsx +++ b/src/mol-plugin/ui/controls.tsx @@ -16,8 +16,9 @@ import { StateTransforms } from '../../mol-plugin/state/transforms'; import { StateTransformer } from '../../mol-state'; import { ModelFromTrajectory } from '../../mol-plugin/state/transforms/model'; import { AnimationControls } from './state/animation'; -import { OverpaintControls } from './structure/overpaint'; -import { RepresentationControls } from './structure/representation'; +import { StructureOverpaintControls } from './structure/overpaint'; +import { StructureRepresentationControls } from './structure/representation'; +import { StructureSelectionControls } from './structure/selection'; export class TrajectoryViewportControls extends PluginUIComponent<{}, { show: boolean, label: string }> { state = { show: false, label: '' } @@ -259,8 +260,9 @@ export class StructureToolsWrapper extends PluginUIComponent { return <div> <div className='msp-section-header'><Icon name='code' /> Structure Tools</div> - <OverpaintControls /> - <RepresentationControls /> + <StructureSelectionControls /> + <StructureOverpaintControls /> + <StructureRepresentationControls /> </div>; } } \ No newline at end of file diff --git a/src/mol-plugin/ui/structure/overpaint.tsx b/src/mol-plugin/ui/structure/overpaint.tsx index 12f845a8d5618774eb14b737597c3ef6f52c6b6b..c158f2801f564f0f155caadacce44b05ae4298c5 100644 --- a/src/mol-plugin/ui/structure/overpaint.tsx +++ b/src/mol-plugin/ui/structure/overpaint.tsx @@ -21,8 +21,8 @@ import { getExpression } from './util'; type OverpaintEachReprCallback = (update: StateBuilder.Root, repr: StateObjectCell<PluginStateObject.Molecule.Structure.Representation3D, StateTransform<typeof StateTransforms.Representation.StructureRepresentation3D>>, rootStructure: Structure, overpaint?: StateObjectCell<any, StateTransform<typeof StateTransforms.Representation.OverpaintStructureRepresentation3D>>) => void const OverpaintManagerTag = 'overpaint-controls' -export class OverpaintControls extends PluginUIComponent<{}, { params: PD.Values<ReturnType<typeof OverpaintControls.getParams>> }> { - state = { params: PD.getDefaultValues(OverpaintControls.getParams(this.plugin)) } +export class StructureOverpaintControls extends PluginUIComponent<{}, { params: PD.Values<ReturnType<typeof StructureOverpaintControls.getParams>> }> { + state = { params: PD.getDefaultValues(StructureOverpaintControls.getParams(this.plugin)) } static getParams = (plugin: PluginContext) => { const { types } = plugin.structureRepresentation.registry @@ -96,7 +96,7 @@ export class OverpaintControls extends PluginUIComponent<{}, { params: PD.Values <button className='msp-btn msp-btn-block'>Current Selection Overpaint</button> </div> <div> - <ParameterControls params={OverpaintControls.getParams(this.plugin)} values={this.state.params} onChange={p => { + <ParameterControls params={StructureOverpaintControls.getParams(this.plugin)} values={this.state.params} onChange={p => { const params = { ...this.state.params, [p.name]: p.value }; this.setState({ params }); }}/> diff --git a/src/mol-plugin/ui/structure/representation.tsx b/src/mol-plugin/ui/structure/representation.tsx index 74d35f0be97375ab32e2a04d5a498e3c9d47f5a8..54e06dfce717987bc7a47d76234ecdfae2dae352 100644 --- a/src/mol-plugin/ui/structure/representation.tsx +++ b/src/mol-plugin/ui/structure/representation.tsx @@ -36,8 +36,8 @@ function getCombinedLoci(mode: 'add' | 'remove' | 'only' | 'all', loci: Structur } } -export class RepresentationControls extends PluginUIComponent<{}, { params: PD.Values<ReturnType<typeof RepresentationControls.getParams>> }> { - state = { params: PD.getDefaultValues(RepresentationControls.getParams(this.plugin)) } +export class StructureRepresentationControls extends PluginUIComponent<{}, { params: PD.Values<ReturnType<typeof StructureRepresentationControls.getParams>> }> { + state = { params: PD.getDefaultValues(StructureRepresentationControls.getParams(this.plugin)) } static getParams = (plugin: PluginContext) => { const { types } = plugin.structureRepresentation.registry @@ -129,7 +129,7 @@ export class RepresentationControls extends PluginUIComponent<{}, { params: PD.V <button className='msp-btn msp-btn-block'>Current Selection Representation</button> </div> <div> - <ParameterControls params={RepresentationControls.getParams(this.plugin)} values={this.state.params} onChange={p => { + <ParameterControls params={StructureRepresentationControls.getParams(this.plugin)} values={this.state.params} onChange={p => { const params = { ...this.state.params, [p.name]: p.value }; this.setState({ params }); }}/> diff --git a/src/mol-plugin/ui/structure/selection.tsx b/src/mol-plugin/ui/structure/selection.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ea60e71c2582596f255cbe2a99d7026f0cd7a5d9 --- /dev/null +++ b/src/mol-plugin/ui/structure/selection.tsx @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import * as React from 'react'; +import { PluginUIComponent } from '../base'; +import { MolScriptBuilder as MS } from '../../../mol-script/language/builder'; +import { StateSelection } from '../../../mol-state'; +import { PluginStateObject } from '../../state/objects'; +import { QueryContext, StructureSelection, QueryFn, Queries as _Queries } from '../../../mol-model/structure'; +import { compile } from '../../../mol-script/runtime/query/compiler'; +import { ButtonsType } from '../../../mol-util/input/input-observer'; +import { EmptyLoci } from '../../../mol-model/loci'; + +const Queries = { + all: () => compile<StructureSelection>(MS.struct.generator.all()), + polymers: () => _Queries.internal.atomicSequence(), + water: () => _Queries.internal.water(), + ligands: () => _Queries.internal.atomicHet(), + coarse: () => _Queries.internal.spheres(), +} + +export class StructureSelectionControls extends PluginUIComponent<{}, {}> { + state = {} + + select = (query: QueryFn<StructureSelection>) => { + const state = this.plugin.state.dataState + const structures = state.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Structure)) + const { structureSelection } = this.plugin.helpers + + structureSelection.clear() + for (const so of structures) { + const s = so.obj!.data + const result = query(new QueryContext(s)) + const loci = StructureSelection.toLoci2(result) + + // TODO use better API when available + this.plugin.interactivity.lociSelections.apply({ + current: { loci }, + buttons: ButtonsType.Flag.Secondary, + modifiers: { shift: false, alt: false, control: true, meta: false } + }) + } + } + + clear = () => { + // TODO use better API when available + this.plugin.interactivity.lociSelections.apply({ + current: { loci: EmptyLoci }, + buttons: ButtonsType.Flag.Secondary, + modifiers: { shift: false, alt: false, control: true, meta: false } + }) + } + + render() { + return <div className='msp-transform-wrapper'> + <div className='msp-transform-header'> + <button className='msp-btn msp-btn-block'>Current Selection</button> + </div> + <div> + <div className='msp-btn-row-group'> + <button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.select(Queries.all())}>All</button> + <button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.clear()}>None</button> + </div> + <div className='msp-btn-row-group'> + <button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.select(Queries.polymers())}>Polymers</button> + <button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.select(Queries.ligands())}>Ligands</button> + <button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.select(Queries.water())}>Water</button> + <button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.select(Queries.coarse())}>Coarse</button> + </div> + </div> + </div> + } +} \ No newline at end of file diff --git a/src/mol-plugin/util/interactivity.ts b/src/mol-plugin/util/interactivity.ts index 87031ce0e1c0f76fe4f3189267579a5fd662ba1e..bce545a963a815be2635ba2e8336bafa57f66b4d 100644 --- a/src/mol-plugin/util/interactivity.ts +++ b/src/mol-plugin/util/interactivity.ts @@ -163,6 +163,7 @@ namespace Interactivity { } } + // TODO create better API that is independent of a `ClickEvent` apply(e: ClickEvent) { const { current, buttons, modifiers } = e const normalized: Loci<ModelLoci> = this.normalizedLoci(current)