Browse Source

measurements ui improvements

David Sehnal 5 years ago
parent
commit
4818f851b3

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

@@ -23,7 +23,7 @@ export type StructureMeasurementCell = StateObjectCell<PluginStateObject.Shape.R
 
 export const StructureMeasurementParams = {
     distanceUnitLabel: PD.Text('\u212B', { isEssential: true }),
-    ...MeasurementRepresentationCommonTextParams
+    textColor: MeasurementRepresentationCommonTextParams.textColor
 }
 const DefaultStructureMeasurementOptions = PD.getDefaultValues(StructureMeasurementParams)
 export type StructureMeasurementOptions = PD.ValuesFor<typeof StructureMeasurementParams>
@@ -63,17 +63,16 @@ class StructureMeasurementManager extends PluginComponent<StructureMeasurementMa
             update.to(cell).update((old: any) => { 
                 old.unitLabel = options.distanceUnitLabel;
                 old.textColor = options.textColor;
-                old.textSize = options.textSize;
             });
         }
         for (const cell of this.state.labels) {
-            update.to(cell).update((old: any) => { old.textColor = options.textColor; old.textSize = options.textSize; });
+            update.to(cell).update((old: any) => { old.textColor = options.textColor; });
         }
         for (const cell of this.state.angles) {
-            update.to(cell).update((old: any) => { old.textColor = options.textColor; old.textSize = options.textSize; });
+            update.to(cell).update((old: any) => { old.textColor = options.textColor; });
         }
         for (const cell of this.state.dihedrals) {
-            update.to(cell).update((old: any) => { old.textColor = options.textColor; old.textSize = options.textSize; });
+            update.to(cell).update((old: any) => { old.textColor = options.textColor; });
         }
         
         if (update.editInfo.count === 0) return;
@@ -102,7 +101,6 @@ class StructureMeasurementManager extends PluginComponent<StructureMeasurementMa
             }, { dependsOn })
             .apply(StateTransforms.Representation.StructureSelectionsDistance3D, {
                 unitLabel: this.state.options.distanceUnitLabel,
-                textSize: this.state.options.textSize,
                 textColor: this.state.options.textColor
             })
 
@@ -133,7 +131,6 @@ class StructureMeasurementManager extends PluginComponent<StructureMeasurementMa
                 label: 'Angle'
             }, { dependsOn })
             .apply(StateTransforms.Representation.StructureSelectionsAngle3D, {
-                textSize: this.state.options.textSize,
                 textColor: this.state.options.textColor
             })
 
@@ -167,7 +164,6 @@ class StructureMeasurementManager extends PluginComponent<StructureMeasurementMa
                 label: 'Dihedral'
             }, { dependsOn })
             .apply(StateTransforms.Representation.StructureSelectionsDihedral3D, {
-                textSize: this.state.options.textSize,
                 textColor: this.state.options.textColor
             })
 
@@ -192,7 +188,6 @@ class StructureMeasurementManager extends PluginComponent<StructureMeasurementMa
                 label: 'Label'
             }, { dependsOn })
             .apply(StateTransforms.Representation.StructureSelectionsLabel3D, {
-                textSize: this.state.options.textSize,
                 textColor: this.state.options.textColor
             })
 

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

@@ -13,7 +13,7 @@ import { EmptyLoci, Loci } from '../../../mol-model/loci';
 import { Structure, StructureElement, StructureSelection } from '../../../mol-model/structure';
 import { Boundary } from '../../../mol-model/structure/structure/util/boundary';
 import { PluginContext } from '../../../mol-plugin/context';
-import { StateObject } from '../../../mol-state';
+import { StateObject, StateObjectRef } from '../../../mol-state';
 import { Task } from '../../../mol-task';
 import { structureElementStatsLabel } from '../../../mol-theme/label';
 import { arrayRemoveAtInPlace } from '../../../mol-util/array';
@@ -419,6 +419,21 @@ export class StructureSelectionManager extends PluginComponent<StructureSelectio
         }))
     }
 
+    fromSelections(ref: StateObjectRef<PluginStateObject.Molecule.Structure.Selections>) {
+        const cell = StateObjectRef.resolveAndCheck(this.plugin.state.dataState, ref);
+        if (!cell || !cell.obj) return;
+
+        if (!PluginStateObject.Molecule.Structure.Selections.is(cell.obj)) {
+            console.warn('fromSelections applied to wrong object type.', cell.obj);
+            return;
+        }
+
+        this.clear();
+        for (const s of cell.obj?.data) {
+            this.fromLoci('set', s.loci);
+        }
+    }
+
     constructor(private plugin: PluginContext) {
         super({ entries: new Map(), additionsHistory: [], stats: SelectionStats() });
 

+ 7 - 6
src/mol-plugin-ui/structure/components.tsx

@@ -282,6 +282,13 @@ class StructureComponentGroup extends PurePluginUIComponent<{ group: StructureCo
 
         return ret;
     }
+    
+    selectAction: ActionMenu.OnSelect = item => {
+        if (!item) return;
+        this.setState({ action: void 0 });
+        (item?.value as any)();
+    }
+
 
     get removeActions(): ActionMenu.Items {
         const ret = [
@@ -298,12 +305,6 @@ class StructureComponentGroup extends PurePluginUIComponent<{ group: StructureCo
         return ret;
     }
 
-    selectAction: ActionMenu.OnSelect = item => {
-        if (!item) return;
-        this.setState({ action: void 0 });
-        (item?.value as any)();
-    }
-
     selectRemoveAction: ActionMenu.OnSelect = item => {
         if (!item) return;
         this.setState({ action: void 0 });

+ 38 - 14
src/mol-plugin-ui/structure/measurements.tsx

@@ -11,7 +11,6 @@ import { StructureMeasurementCell, StructureMeasurementOptions, StructureMeasure
 import { StructureSelectionHistoryEntry } from '../../mol-plugin-state/manager/structure/selection';
 import { PluginStateObject } from '../../mol-plugin-state/objects';
 import { PluginCommands } from '../../mol-plugin/commands';
-import { State } from '../../mol-state';
 import { angleLabel, dihedralLabel, distanceLabel, lociLabel } from '../../mol-theme/label';
 import { FiniteArray } from '../../mol-util/type-helpers';
 import { CollapsableControls, PurePluginUIComponent } from '../base';
@@ -19,6 +18,7 @@ import { ActionMenu } from '../controls/action-menu';
 import { ExpandGroup, IconButton, ToggleButton } from '../controls/common';
 import { Icon } from '../controls/icons';
 import { ParameterControls } from '../controls/parameters';
+import { UpdateTransformControl } from '../state/update-transform';
 
 // TODO details, options (e.g. change text for labels)
 
@@ -56,13 +56,13 @@ export class MeasurementList extends PurePluginUIComponent {
     render() {
         const measurements = this.plugin.managers.structure.measurement.state;
 
-        return <>
+        return <div style={{ marginTop: '6px' }}>
             {this.renderGroup(measurements.labels, 'Labels')}
             {this.renderGroup(measurements.distances, 'Distances')}
             {this.renderGroup(measurements.angles, 'Angles')}
             {this.renderGroup(measurements.dihedrals, 'Dihedrals')}
             {this.renderGroup(measurements.orientations, 'Orientations')}
-        </>
+        </div>;
     }
 }
 
@@ -211,12 +211,12 @@ class MeasurementsOptions extends PurePluginUIComponent<{}, { isDisabled: boolea
     }
 }
 
-class MeasurementEntry extends PurePluginUIComponent<{ cell: StructureMeasurementCell }> {
+class MeasurementEntry extends PurePluginUIComponent<{ cell: StructureMeasurementCell }, { showUpdate: boolean }> {
+    state = { showUpdate: false }
+
     componentDidMount() {
         this.subscribe(this.plugin.events.state.cell.stateUpdated, e => {
-            if (State.ObjectEvent.isCell(e, this.props.cell)) {
-                this.forceUpdate();
-            }
+            this.forceUpdate();
         });
     }
 
@@ -249,6 +249,8 @@ class MeasurementEntry extends PurePluginUIComponent<{ cell: StructureMeasuremen
         this.plugin.managers.interactivity.lociHighlights.clearHighlights();
     }
 
+    toggleUpdate = () => this.setState({ showUpdate: !this.state.showUpdate });
+
     focus = () => {
         const selections = this.selections;
         if (!selections) return;
@@ -270,18 +272,40 @@ class MeasurementEntry extends PurePluginUIComponent<{ cell: StructureMeasuremen
         }
     }
 
+    get actions(): ActionMenu.Items {
+        this.props.cell.sourceRef
+        return [ActionMenu.Item('Select This', 'flash', () => this.plugin.managers.structure.selection.fromSelections(this.props.cell.sourceRef!))];
+    }
+    
+    selectAction: ActionMenu.OnSelect = item => {
+        if (!item) return;
+        this.setState({ showUpdate: false });
+        (item?.value as any)();
+    }
+
     render() {
         const { cell } = this.props;
         const { obj } = cell;
         if (!obj) return null;
 
-        return <div className='msp-btn-row-group' key={obj.id} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight}>
-            <button className='msp-btn msp-btn-block msp-form-control' title='Click to focus. Hover to highlight.' onClick={this.focus} style={{ width: 'auto' }}>
-                <span dangerouslySetInnerHTML={{ __html: this.label }} />
-            </button>
-            <IconButton small={true} customClass='msp-form-control' onClick={this.delete} icon='remove' style={{ flex: '0 0 32px' }} title='Delete' />
-            <IconButton small={true} customClass='msp-form-control' onClick={this.toggleVisibility} icon='eye' style={{ flex: '0 0 32px' }} title={cell.state.isHidden ? 'Show' : 'Hide'} toggleState={!cell.state.isHidden} />
-        </div>
+        return <>
+            <div className='msp-btn-row-group' key={obj.id} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight}>
+                <button className='msp-btn msp-btn-block msp-form-control' title='Click to focus. Hover to highlight.' onClick={this.focus} style={{ width: 'auto', textAlign: 'left' }}>
+                    <span dangerouslySetInnerHTML={{ __html: this.label }} />
+                </button>
+                <IconButton small={true} customClass='msp-form-control' onClick={this.toggleVisibility} icon='eye' style={{ flex: '0 0 32px' }} title={cell.state.isHidden ? 'Show' : 'Hide'} toggleState={!cell.state.isHidden} />
+                <IconButton small={true} customClass='msp-form-control' onClick={this.delete} icon='remove' style={{ flex: '0 0 32px' }} title='Delete' />
+                <IconButton small={true} customClass='msp-form-control' onClick={this.toggleUpdate} icon='dot-3' style={{ flex: '0 0 32px' }} title={cell.state.isHidden ? 'Show' : 'Hide'} toggleState={this.state.showUpdate} />
+            </div>
+            {this.state.showUpdate && <>
+                <ActionMenu items={this.actions} onSelect={this.selectAction} />
+                <div className='msp-control-offset'>
+                    <ExpandGroup header='Options' noOffset>
+                        <UpdateTransformControl state={cell.parent} transform={cell.transform} customHeader='none' />
+                    </ExpandGroup>
+                </div>
+            </>}
+        </>
     }
 }