objects.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /**
  2. * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import * as React from 'react';
  7. import { CollapsableControls, CollapsableState } from '../base';
  8. import { StateTransformer, StateTransform } from '../../mol-state';
  9. import { ModelRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
  10. import { StateTransforms } from '../../mol-plugin-state/transforms';
  11. import { StructureBuilderTags } from '../../mol-plugin-state/builder/structure';
  12. import { IconButton } from '../controls/common';
  13. interface ObjectControlState extends CollapsableState {
  14. isBusy: boolean,
  15. showOptions: boolean,
  16. }
  17. export class ObjectControls extends CollapsableControls<{}, ObjectControlState> {
  18. protected defaultState(): ObjectControlState {
  19. return {
  20. header: 'Objects',
  21. isCollapsed: false,
  22. isBusy: false,
  23. showOptions: false
  24. };
  25. }
  26. componentDidMount() {
  27. this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, () => this.forceUpdate());
  28. this.subscribe(this.plugin.behaviors.state.isBusy, v => {
  29. this.setState({ isBusy: v })
  30. });
  31. }
  32. getUnitcell(model: ModelRef) {
  33. return model.genericRepresentations?.filter(r => {
  34. return r.cell.transform.transformer === StateTransforms.Representation.ModelUnitcell3D
  35. })[0]
  36. }
  37. toggleVisible = (e: React.MouseEvent<HTMLElement>) => {
  38. e.preventDefault();
  39. e.currentTarget.blur();
  40. for (const model of this.plugin.managers.structure.hierarchy.current.models) {
  41. const unitcell = this.getUnitcell(model)
  42. if (unitcell) {
  43. this.plugin.state.data.updateCellState(unitcell.cell.transform.ref, { isHidden: !unitcell.cell.state.isHidden });
  44. }
  45. }
  46. }
  47. isVisible() {
  48. for (const model of this.plugin.managers.structure.hierarchy.current.models) {
  49. const unitcell = this.getUnitcell(model)
  50. if (unitcell && !unitcell.cell.state.isHidden) return true
  51. }
  52. return false
  53. }
  54. async createUnitcell(model: ModelRef, params?: StateTransformer.Params<StateTransforms['Representation']['ModelUnitcell3D']>, initialState?: Partial<StateTransform.State>) {
  55. const state = this.plugin.state.data;
  56. const unitcell = state.build().to(model.cell)
  57. .apply(StateTransforms.Representation.ModelUnitcell3D, params, { tags: StructureBuilderTags.ModelGenericRepresentation, state: initialState });
  58. await this.plugin.updateDataState(unitcell, { revertOnError: true });
  59. return unitcell.selector;
  60. }
  61. ensureUnitcell = async () => {
  62. for (const model of this.plugin.managers.structure.hierarchy.current.models) {
  63. if (!this.getUnitcell(model)) await this.createUnitcell(model)
  64. }
  65. }
  66. highlight = (e: React.MouseEvent<HTMLElement>) => {
  67. e.preventDefault();
  68. // TODO
  69. // PluginCommands.Interactivity.Object.Highlight(this.plugin, { state: this.props.group[0].cell.parent, ref: this.props.group.map(c => c.cell.transform.ref) });
  70. }
  71. clearHighlight = (e: React.MouseEvent<HTMLElement>) => {
  72. e.preventDefault();
  73. // TODO
  74. // PluginCommands.Interactivity.ClearHighlights(this.plugin);
  75. }
  76. focus = () => {
  77. // TODO
  78. // const sphere = this.pivot.cell.obj?.data.boundary.sphere;
  79. // if (sphere) this.plugin.managers.camera.focusSphere(sphere);
  80. }
  81. toggleOptions = () => {
  82. // TODO
  83. this.setState({ showOptions: !this.state.showOptions })
  84. }
  85. renderControls() {
  86. const label = 'Unitcell'
  87. const isVisible = this.isVisible()
  88. return <>
  89. <div className='msp-control-row'>
  90. <button className='msp-control-button-label' title={`${label}. Click to focus.`} onClick={this.focus} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight} style={{ textAlign: 'left' }}>
  91. {label}
  92. </button>
  93. <div className='msp-select-row'>
  94. <IconButton onClick={this.toggleVisible} icon='visual-visibility' toggleState={isVisible} title={`${isVisible ? 'Hide' : 'Show'} component`} disabled={this.state.isBusy} style={{ flex: '0 0 40px' }} />
  95. <IconButton onClick={this.toggleOptions} icon='cog' title='Options' toggleState={this.state.showOptions} disabled={this.state.isBusy} style={{ flex: '0 0 40px' }} />
  96. </div>
  97. </div>
  98. <div className='msp-control-group-header msp-flex-row' style={{ marginTop: '1px' }}>
  99. <button className='msp-btn msp-form-control msp-flex-item msp-no-overflow' onClick={this.ensureUnitcell}>
  100. Unitcell
  101. </button>
  102. </div>
  103. </>;
  104. }
  105. }