RcsbView.tsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import * as React from "react";
  2. import {RcsbFvDOMConstants} from "../../../RcsbFvConstants/RcsbFvConstants";
  3. import {unmount} from "@rcsb/rcsb-saguaro-app";
  4. import {AbstractView, AbstractViewInterface} from "../AbstractView";
  5. import {RcsbFvBoardConfigInterface, RcsbFvTrackDataElementInterface} from "@rcsb/rcsb-saguaro";
  6. import {OperatorInfo} from "../../../RcsbFvStructure/StructureViewerInterface";
  7. import {RcsbFvAdditionalConfig, RcsbFvModulePublicInterface} from "@rcsb/rcsb-saguaro-app/build/dist/RcsbFvWeb/RcsbFvModule/RcsbFvModuleInterface";
  8. import {DataContainer} from "../../../Utils/DataContainer";
  9. import {
  10. PfvManagerInterface,
  11. PfvManagerFactoryInterface
  12. } from "./PfvManagerFactoryInterface";
  13. import {
  14. CallbackManagerFactoryInterface,
  15. CallbackManagerInterface
  16. } from "./CallbackManagerFactoryInterface";
  17. export interface RcsbViewInterface<T,R,U> {
  18. rcsbId: string;
  19. additionalConfig?: RcsbFvAdditionalConfig & {operatorChangeCallback?:(operatorInfo: OperatorInfo)=>void};
  20. useOperatorsFlag?:boolean;
  21. pfvParams:T;
  22. pfvManagerFactory: PfvManagerFactoryInterface<T,R,U>;
  23. callbackManagerFactory: CallbackManagerFactoryInterface<R,U>;
  24. buildPfvOnMount?: boolean;
  25. }
  26. export class RcsbView<T,R,U> extends AbstractView<RcsbViewInterface<T,R,U>, {}, R>{
  27. private boardConfigContainer: DataContainer<Partial<RcsbFvBoardConfigInterface>> = new DataContainer();
  28. private rcsbFvContainer: DataContainer<RcsbFvModulePublicInterface> = new DataContainer<RcsbFvModulePublicInterface>();
  29. private readonly callbackManager: CallbackManagerInterface<U>;
  30. private readonly pfvFactory: PfvManagerInterface;
  31. constructor(props:RcsbViewInterface<T,R,U> & AbstractViewInterface<R>) {
  32. super(props);
  33. this.pfvFactory = this.props.pfvManagerFactory.getPfvManager({
  34. ...this.props.pfvParams,
  35. rcsbFvContainer: this.rcsbFvContainer,
  36. stateManager: this.props.stateManager,
  37. structureViewer: this.props.structureViewer,
  38. boardConfigContainer: this.boardConfigContainer,
  39. rcsbFvDivId: this.rcsbFvDivId,
  40. pfvChangeCallback: this.pfvChangeCallback.bind(this),
  41. additionalConfig: this.props.additionalConfig,
  42. useOperatorsFlag: this.props.useOperatorsFlag
  43. });
  44. this.callbackManager = this.props.callbackManagerFactory.getCallbackManager({
  45. rcsbFvContainer: this.rcsbFvContainer,
  46. stateManager: this.props.stateManager,
  47. structureViewer: this.props.structureViewer,
  48. pfvFactory: this.pfvFactory
  49. });
  50. }
  51. additionalContent(): JSX.Element {
  52. return (
  53. <div style={{marginTop:10}}>
  54. <div>
  55. <div id={RcsbFvDOMConstants.SELECT_BUTTON_PFV_ID} style={{display:"inline-block"}}/>
  56. </div>
  57. <div style={{position:"absolute", top:5, right:5}} >
  58. <a style={{textDecoration:"none", color:"#337ab7", cursor:"pointer", marginRight:15}} target={"_blank"} href={"/docs/sequence-viewers/3d-protein-feature-view"}>
  59. Help
  60. </a>
  61. <a style={{textDecoration:"none", color: "#337ab7", cursor:"pointer"}} onClick={()=>{this.props.unmount(true, ()=>{
  62. window.history.back();
  63. })}}>
  64. Back
  65. </a>
  66. </div>
  67. </div>
  68. );
  69. }
  70. async componentDidMount (): Promise<void> {
  71. super.componentDidMount();
  72. const width: number | undefined = document.getElementById(this.componentDivId)?.getBoundingClientRect().width;
  73. if(width == null)
  74. return;
  75. const trackWidth: number = width - 190 - 55;
  76. this.boardConfigContainer.set({
  77. ...this.props.additionalConfig?.boardConfig,
  78. trackWidth: trackWidth,
  79. highlightHoverPosition:true,
  80. highlightHoverElement:true,
  81. elementClickCallBack:(e:RcsbFvTrackDataElementInterface)=>{
  82. this.elementClickCallback(e);
  83. if(typeof this.props.additionalConfig?.boardConfig?.elementClickCallBack === "function")
  84. this.props.additionalConfig?.boardConfig.elementClickCallBack(e);
  85. },
  86. selectionChangeCallBack:(selection: Array<RcsbFvTrackDataElementInterface>)=>{
  87. this.selectionChangeCallback(selection);
  88. if(typeof this.props.additionalConfig?.boardConfig?.selectionChangeCallBack === "function")
  89. this.props.additionalConfig?.boardConfig.selectionChangeCallBack(selection);
  90. },
  91. highlightHoverCallback:(selection: RcsbFvTrackDataElementInterface[])=>{
  92. this.highlightHoverCallback(selection);
  93. if(typeof this.props.additionalConfig?.boardConfig?.highlightHoverCallback === "function")
  94. this.props.additionalConfig?.boardConfig.highlightHoverCallback(selection);
  95. },
  96. });
  97. if(this.props.buildPfvOnMount)
  98. this.rcsbFvContainer.set(await this.pfvFactory.create());
  99. }
  100. componentWillUnmount() {
  101. super.componentWillUnmount();
  102. unmount(this.rcsbFvDivId);
  103. }
  104. async structureSelectionCallback(): Promise<void> {
  105. await this.pluginSelectCallback('select');
  106. }
  107. async structureHoverCallback(): Promise<void> {
  108. await this.pluginSelectCallback('hover');
  109. }
  110. representationChangeCallback(): void{
  111. //TODO
  112. }
  113. async updateDimensions(): Promise<void> {
  114. const width: number = window.document.getElementById(this.componentDivId)?.getBoundingClientRect().width ?? 0;
  115. const trackWidth: number = width - 190 - 55;
  116. this.boardConfigContainer.set({...this.boardConfigContainer.get(), trackWidth});
  117. const select = this.rcsbFvContainer.get()?.getFv().getSelection("select");
  118. const dom = this.rcsbFvContainer.get()?.getFv().getDomain();
  119. await this.rcsbFvContainer.get()?.getFv().updateBoardConfig({boardConfigData:{trackWidth:trackWidth}})
  120. if(select)
  121. this.rcsbFvContainer.get()?.getFv().setSelection({
  122. elements: select.map(s=>({begin:s.rcsbFvTrackDataElement.begin, end:s.rcsbFvTrackDataElement.end })),
  123. mode:"select"
  124. });
  125. if(dom) this.rcsbFvContainer.get()?.getFv().setDomain(dom);
  126. return void 0;
  127. }
  128. async modelChangeCallback(defaultAuthId?: string, defaultOperatorName?:string): Promise<void> {
  129. await this.callbackManager.modelChangeCallback(defaultAuthId, defaultOperatorName);
  130. }
  131. private async pluginSelectCallback(mode:'select'|'hover'): Promise<void> {
  132. await this.callbackManager.structureViewerSelectionCallback(mode);
  133. }
  134. private async pfvChangeCallback(context: U): Promise<void>{
  135. await this.callbackManager.pfvChangeCallback(context);
  136. }
  137. private highlightHoverCallback(selection: RcsbFvTrackDataElementInterface[]): void {
  138. this.callbackManager.highlightHoverCallback(selection);
  139. }
  140. private selectionChangeCallback(selection: Array<RcsbFvTrackDataElementInterface>): void {
  141. this.callbackManager.pfvSelectionChangeCallback(selection);
  142. }
  143. private elementClickCallback(e:RcsbFvTrackDataElementInterface): void {
  144. this.callbackManager.featureClickCallback(e);
  145. }
  146. }