Browse Source

wip, generic representation entry

Alexander Rose 5 years ago
parent
commit
83fb28cc9d

+ 1 - 1
src/mol-plugin-ui/state/common.tsx

@@ -240,7 +240,7 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
         </ExpandGroup>;
     }
 
-    renderSimple() {        
+    renderSimple() {
         const info = this.getInfo();
         const canApply = this.canApply();
         const apply = <div className='msp-control-row msp-select-row'>

+ 5 - 5
src/mol-plugin-ui/structure/unitcell.tsx → src/mol-plugin-ui/structure/generic.tsx

@@ -6,14 +6,14 @@
  */
 
 import * as React from 'react';
-import { ModelUnitcellRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
+import { HierarchyRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
 import { PluginCommands } from '../../mol-plugin/commands';
 import { State } from '../../mol-state';
 import { PurePluginUIComponent } from '../base';
 import { IconButton } from '../controls/common';
 import { UpdateTransformControl } from '../state/update-transform';
 
-export class UnitcellEntry extends PurePluginUIComponent<{ refs: ModelUnitcellRef[] }, { showOptions: boolean }> {
+export class GenericEntry<T extends HierarchyRef> extends PurePluginUIComponent<{ refs: T[], labelMultiple?: string }, { showOptions: boolean }> {
     state = { showOptions: false }
 
     componentDidMount() {
@@ -59,7 +59,7 @@ export class UnitcellEntry extends PurePluginUIComponent<{ refs: ModelUnitcellRe
     toggleOptions = () => this.setState({ showOptions: !this.state.showOptions })
 
     render() {
-        const { refs } = this.props;
+        const { refs, labelMultiple } = this.props;
         if (refs.length === 0) return null;
 
         const pivot = refs[0];
@@ -71,11 +71,11 @@ export class UnitcellEntry extends PurePluginUIComponent<{ refs: ModelUnitcellRe
             label = obj?.label;
             description = obj?.description;
         } else {
-            label = 'Unitcells';
+            label = `${refs.length} ${labelMultiple || 'Objects'}`;
         }
 
         return <>
-            <div className='msp-btn-row-group' style={{ marginTop: '6px' }}>
+            <div className='msp-btn-row-group'>
                 <button className='msp-form-control msp-control-button-label' title={`${label}. Click to focus.`} onClick={this.focus} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight} style={{ textAlign: 'left' }}>
                     {label} <small>{description}</small>
                 </button>

+ 20 - 3
src/mol-plugin-ui/structure/source.tsx

@@ -2,6 +2,7 @@
  * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
 import * as React from 'react';
@@ -14,7 +15,7 @@ import { PluginCommands } from '../../mol-plugin/commands';
 import { StateTransforms } from '../../mol-plugin-state/transforms';
 import { memoize1 } from '../../mol-util/memoize';
 import { StructureHierarchyManager } from '../../mol-plugin-state/manager/structure/hierarchy';
-import { UnitcellEntry } from './unitcell';
+import { GenericEntry } from './generic';
 
 interface StructureSourceControlState extends CollapsableState {
     isBusy: boolean,
@@ -257,7 +258,20 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo
         }
         if (refs.length === 0) return null;
 
-        return <UnitcellEntry refs={refs} />;
+        return <GenericEntry refs={refs} labelMultiple='Unitcells' />;
+    }
+
+    get customControls(): JSX.Element[] | null {
+        const controls: JSX.Element[] = []
+        this.plugin.customSourceControls.forEach((provider, key) => {
+            const [refs, labelMultiple] = provider(this.plugin.managers.structure.hierarchy.selection)
+            if (refs.length > 0) {
+                controls.push(<div key={key}>
+                    <GenericEntry refs={refs} labelMultiple={labelMultiple} />
+                </div>)
+            }
+        })
+        return controls.length > 0 ? controls : null
     }
 
     renderControls() {
@@ -275,7 +289,10 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo
             {this.state.show === 'actions' && <ActionMenu items={actions} onSelect={this.selectAction} />}
             {this.modelIndex}
             {this.structureType}
-            {this.unitcell}
+            <div style={{ marginTop: '6px' }}>
+                {this.unitcell}
+                {this.customControls}
+            </div>
         </>;
     }
 }

+ 27 - 0
src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts

@@ -13,6 +13,7 @@ import { PluginStateTransform, PluginStateObject } from '../../../../../mol-plug
 import { Task } from '../../../../../mol-task';
 import { PluginContext } from '../../../../context';
 import { StateTransformer, StateAction, StateObject } from '../../../../../mol-state';
+import { GenericRepresentationRef } from '../../../../../mol-plugin-state/manager/structure/hierarchy-state';
 
 const Tag = AssemblySymmetry.Tag
 
@@ -30,6 +31,29 @@ export const RCSBAssemblySymmetry = PluginBehavior.create<{ autoAttach: boolean
             this.ctx.state.data.actions.add(InitAssemblySymmetry3D)
             this.ctx.customStructureProperties.register(this.provider, this.params.autoAttach);
             this.ctx.representation.structure.themes.colorThemeRegistry.add(AssemblySymmetryClusterColorThemeProvider)
+
+            this.ctx.customSourceControls.set(Tag.Representation, selection => {
+                const refs: GenericRepresentationRef[] = []
+                selection.structures.forEach(structure => {
+                    const symmRepr = structure.genericRepresentations?.filter(r => r.cell.transform.transformer.id === AssemblySymmetry3D.id)[0]
+                    if (symmRepr) refs.push(symmRepr)
+                })
+                return [refs, 'Symmetries']
+            })
+
+            // TODO this should probably be done via a hierarchy preset
+            this.subscribeObservable(this.ctx.managers.structure.hierarchy.behaviors.selection, selection => {
+                for (const structure of selection.structures) {
+                    const symmRepr = structure.genericRepresentations?.filter(r => r.cell.transform.transformer.id === AssemblySymmetry3D.id)[0]
+
+                    if (!symmRepr) {
+                        const state = this.ctx.state.data;
+                        const symmReprBuilder = state.build().to(structure.cell.transform.ref)
+                            .apply(AssemblySymmetry3D, { symmetryIndex: 0 }, { state: {} });
+                        this.ctx.updateDataState(symmReprBuilder, { revertOnError: true });
+                    }
+                }
+            })
         }
 
         update(p: { autoAttach: boolean }) {
@@ -43,6 +67,7 @@ export const RCSBAssemblySymmetry = PluginBehavior.create<{ autoAttach: boolean
             this.ctx.state.data.actions.remove(InitAssemblySymmetry3D)
             this.ctx.customStructureProperties.unregister(this.provider.descriptor.name);
             this.ctx.representation.structure.themes.colorThemeRegistry.remove(AssemblySymmetryClusterColorThemeProvider)
+            this.ctx.customSourceControls.delete(Tag.Representation)
         }
     },
     params: () => ({
@@ -51,6 +76,8 @@ export const RCSBAssemblySymmetry = PluginBehavior.create<{ autoAttach: boolean
     })
 });
 
+//
+
 const InitAssemblySymmetry3D = StateAction.build({
     display: {
         name: 'Assembly Symmetry',

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

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -50,6 +50,7 @@ import { PluginToastManager } from './util/toast';
 import { ViewportScreenshotHelper } from './util/viewport-screenshot';
 import { PLUGIN_VERSION, PLUGIN_VERSION_DATE } from './version';
 import { Representation } from '../mol-repr/representation';
+import { HierarchyRef } from '../mol-plugin-state/manager/structure/hierarchy-state';
 
 export class PluginContext {
     private disposed = false;
@@ -143,6 +144,7 @@ export class PluginContext {
     readonly customModelProperties = new CustomProperty.Registry<Model>();
     readonly customStructureProperties = new CustomProperty.Registry<Structure>();
     readonly customParamEditors = new Map<string, StateTransformParameters.Class>();
+    readonly customSourceControls = new Map<string, (selection: StructureHierarchyManager['selection']) => [HierarchyRef[], string]>();
 
     readonly helpers = {
         substructureParent: new SubstructureParentHelper(this),