|
@@ -7,81 +7,81 @@
|
|
|
|
|
|
import * as React from 'react';
|
|
|
import { StructureSelectionQueries, StructureSelectionQuery } from '../../mol-plugin-state/helpers/structure-selection-query';
|
|
|
-import { InteractivityManager } from '../../mol-plugin-state/manager/interactivity';
|
|
|
import { StructureComponentManager } from '../../mol-plugin-state/manager/structure/component';
|
|
|
import { StructureRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
|
|
|
import { StructureSelectionModifier } from '../../mol-plugin-state/manager/structure/selection';
|
|
|
import { memoizeLatest } from '../../mol-util/memoize';
|
|
|
import { ParamDefinition } from '../../mol-util/param-definition';
|
|
|
import { stripTags } from '../../mol-util/string';
|
|
|
-import { CollapsableControls, CollapsableState, PurePluginUIComponent, PluginUIComponent } from '../base';
|
|
|
+import { PluginUIComponent, PurePluginUIComponent } from '../base';
|
|
|
import { ActionMenu } from '../controls/action-menu';
|
|
|
-import { ControlGroup, ToggleButton, IconButton, Button } from '../controls/common';
|
|
|
-import { ParameterControls } from '../controls/parameters';
|
|
|
+import { Button, ControlGroup, IconButton, ToggleButton } from '../controls/common';
|
|
|
+import { ParameterControls, ParamOnChange, PureSelectControl } from '../controls/parameters';
|
|
|
+import { InteractivityManager } from '../../mol-plugin-state/manager/interactivity';
|
|
|
|
|
|
const StructureSelectionParams = {
|
|
|
granularity: InteractivityManager.Params.granularity,
|
|
|
}
|
|
|
|
|
|
-interface StructureSelectionControlsState extends CollapsableState {
|
|
|
- isEmpty: boolean,
|
|
|
- isBusy: boolean,
|
|
|
-}
|
|
|
-
|
|
|
-export class StructureSelectionControls<P, S extends StructureSelectionControlsState> extends CollapsableControls<P, S> {
|
|
|
- componentDidMount() {
|
|
|
- this.subscribe(this.plugin.managers.structure.selection.events.changed, () => {
|
|
|
- this.forceUpdate()
|
|
|
- });
|
|
|
-
|
|
|
- this.subscribe(this.plugin.managers.interactivity.events.propsUpdated, () => {
|
|
|
- this.forceUpdate()
|
|
|
- });
|
|
|
-
|
|
|
- this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, c => {
|
|
|
- const isEmpty = c.structures.length === 0;
|
|
|
- if (this.state.isEmpty !== isEmpty) {
|
|
|
- this.setState({ isEmpty });
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- get isDisabled() {
|
|
|
- return this.state.isBusy || this.state.isEmpty
|
|
|
- }
|
|
|
-
|
|
|
- setProps = (props: any) => {
|
|
|
- this.plugin.managers.interactivity.setProps(props);
|
|
|
- }
|
|
|
-
|
|
|
- get values () {
|
|
|
- return {
|
|
|
- granularity: this.plugin.managers.interactivity.props.granularity,
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- defaultState() {
|
|
|
- return {
|
|
|
- isCollapsed: false,
|
|
|
- header: 'Selection',
|
|
|
-
|
|
|
- isEmpty: true,
|
|
|
- isBusy: false,
|
|
|
-
|
|
|
- brand: { name: 'Sel', accent: 'red' }
|
|
|
- } as S
|
|
|
- }
|
|
|
-
|
|
|
- renderControls() {
|
|
|
- return <>
|
|
|
- <ParameterControls params={StructureSelectionParams} values={this.values} onChangeValues={this.setProps} />
|
|
|
- <StructureSelectionActionsControls />
|
|
|
- <div style={{ margin: '6px 0' }}>
|
|
|
- <StructureSelectionStatsControls />
|
|
|
- </div>
|
|
|
- </>
|
|
|
- }
|
|
|
-}
|
|
|
+// interface StructureSelectionControlsState extends CollapsableState {
|
|
|
+// isEmpty: boolean,
|
|
|
+// isBusy: boolean,
|
|
|
+// }
|
|
|
+
|
|
|
+// export class StructureSelectionControls<P, S extends StructureSelectionControlsState> extends CollapsableControls<P, S> {
|
|
|
+// componentDidMount() {
|
|
|
+// this.subscribe(this.plugin.managers.structure.selection.events.changed, () => {
|
|
|
+// this.forceUpdate()
|
|
|
+// });
|
|
|
+
|
|
|
+// this.subscribe(this.plugin.managers.interactivity.events.propsUpdated, () => {
|
|
|
+// this.forceUpdate()
|
|
|
+// });
|
|
|
+
|
|
|
+// this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, c => {
|
|
|
+// const isEmpty = c.structures.length === 0;
|
|
|
+// if (this.state.isEmpty !== isEmpty) {
|
|
|
+// this.setState({ isEmpty });
|
|
|
+// }
|
|
|
+// });
|
|
|
+// }
|
|
|
+
|
|
|
+// get isDisabled() {
|
|
|
+// return this.state.isBusy || this.state.isEmpty
|
|
|
+// }
|
|
|
+
|
|
|
+// setProps = (props: any) => {
|
|
|
+// this.plugin.managers.interactivity.setProps(props);
|
|
|
+// }
|
|
|
+
|
|
|
+// get values () {
|
|
|
+// return {
|
|
|
+// granularity: this.plugin.managers.interactivity.props.granularity,
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// defaultState() {
|
|
|
+// return {
|
|
|
+// isCollapsed: false,
|
|
|
+// header: 'Selection',
|
|
|
+
|
|
|
+// isEmpty: true,
|
|
|
+// isBusy: false,
|
|
|
+
|
|
|
+// brand: { name: 'Sel', accent: 'red' }
|
|
|
+// } as S
|
|
|
+// }
|
|
|
+
|
|
|
+// renderControls() {
|
|
|
+// return <>
|
|
|
+// {/* <ParameterControls params={StructureSelectionParams} values={this.values} onChangeValues={this.setProps} />
|
|
|
+// <StructureSelectionActionsControls /> */}
|
|
|
+// <StructureSelectionStatsControls />
|
|
|
+// {/* <div style={{ margin: '6px 0' }}>
|
|
|
+// </div> */}
|
|
|
+// </>
|
|
|
+// }
|
|
|
+// }
|
|
|
|
|
|
interface StructureSelectionActionsControlsState {
|
|
|
isEmpty: boolean,
|
|
@@ -115,11 +115,15 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str
|
|
|
|
|
|
this.subscribe(this.plugin.behaviors.state.isBusy, v => {
|
|
|
this.setState({ isBusy: v, action: void 0 })
|
|
|
- })
|
|
|
+ });
|
|
|
+
|
|
|
+ this.subscribe(this.plugin.managers.interactivity.events.propsUpdated, () => {
|
|
|
+ this.forceUpdate()
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
get isDisabled() {
|
|
|
- return this.state.isBusy || this.state.isEmpty
|
|
|
+ return this.state.isBusy || this.state.isEmpty;
|
|
|
}
|
|
|
|
|
|
set = (modifier: StructureSelectionModifier, selectionQuery: StructureSelectionQuery) => {
|
|
@@ -163,7 +167,14 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str
|
|
|
toggleSet = this.showAction('set')
|
|
|
toggleColor = this.showAction('color')
|
|
|
|
|
|
+ setGranuality: ParamOnChange = ({ value }) => {
|
|
|
+ this.plugin.managers.interactivity.setProps({ granularity: value });
|
|
|
+ }
|
|
|
+
|
|
|
+ turnOff = () => this.plugin.selectionMode = false;
|
|
|
+
|
|
|
render() {
|
|
|
+ const granularity = this.plugin.managers.interactivity.props.granularity;
|
|
|
return <>
|
|
|
<div className='msp-flex-row'>
|
|
|
<ToggleButton icon='union' title={ActionHeader.get('add')} toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} />
|
|
@@ -171,16 +182,22 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str
|
|
|
<ToggleButton icon='intersect' title={ActionHeader.get('intersect')} toggle={this.toggleIntersect} isSelected={this.state.action === 'intersect'} disabled={this.isDisabled} />
|
|
|
<ToggleButton icon='set' title={ActionHeader.get('set')} toggle={this.toggleSet} isSelected={this.state.action === 'set'} disabled={this.isDisabled} />
|
|
|
<ToggleButton icon='brush' title='Color' toggle={this.toggleColor} isSelected={this.state.action === 'color'} disabled={this.isDisabled} />
|
|
|
+ <PureSelectControl title={`Picking Level`} param={StructureSelectionParams.granularity} name='granularity' value={granularity} onChange={this.setGranuality} isDisabled={this.isDisabled} />
|
|
|
+ <IconButton icon='cancel' title='Turn selection mode off' onClick={this.turnOff} />
|
|
|
</div>
|
|
|
- {(this.state.action && this.state.action !== 'color') && <ActionMenu header={ActionHeader.get(this.state.action as StructureSelectionModifier)} items={this.queries} onSelect={this.selectQuery} />}
|
|
|
- {this.state.action === 'color' && <ControlGroup header='Color' initialExpanded={true} hideExpander={true} hideOffset={false} onHeaderClick={this.toggleColor} topRightIcon='off'>
|
|
|
- <ApplyColorControls />
|
|
|
- </ControlGroup>}
|
|
|
+ {(this.state.action && this.state.action !== 'color') && <div className='msp-selection-viewport-controls-actions'>
|
|
|
+ <ActionMenu header={ActionHeader.get(this.state.action as StructureSelectionModifier)} items={this.queries} onSelect={this.selectQuery} noOffset />
|
|
|
+ </div>}
|
|
|
+ {this.state.action === 'color' && <div className='msp-selection-viewport-controls-actions'>
|
|
|
+ <ControlGroup header='Color' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleColor} topRightIcon='off'>
|
|
|
+ <ApplyColorControls />
|
|
|
+ </ControlGroup>
|
|
|
+ </div>}
|
|
|
</>
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-export class StructureSelectionStatsControls extends PluginUIComponent<{}, { isEmpty: boolean, isBusy: boolean }> {
|
|
|
+export class StructureSelectionStatsControls extends PluginUIComponent<{ hideOnEmpty?: boolean }, { isEmpty: boolean, isBusy: boolean }> {
|
|
|
state = {
|
|
|
isEmpty: true,
|
|
|
isBusy: false
|
|
@@ -239,6 +256,8 @@ export class StructureSelectionStatsControls extends PluginUIComponent<{}, { isE
|
|
|
const stats = this.plugin.managers.structure.selection.stats
|
|
|
const empty = stats.structureCount === 0 || stats.elementCount === 0;
|
|
|
|
|
|
+ if (empty && this.props.hideOnEmpty) return null;
|
|
|
+
|
|
|
return <>
|
|
|
<div className='msp-flex-row'>
|
|
|
<Button noOverflow onClick={this.focus} title='Click to Focus Selection' disabled={empty} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight}
|