structure-representation.tsx 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /**
  2. * Copyright (c) 2018 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 { StructureRepresentation, StructureProps } from 'mol-geo/representation/structure';
  8. import Viewer from 'mol-view/viewer';
  9. import { VisualQuality, VisualQualityNames } from 'mol-geo/representation/util';
  10. import { ColorThemeProps, ColorThemeName, ColorThemeNames, ColorTheme } from 'mol-view/theme/color';
  11. import { Color } from 'mol-util/color';
  12. import { Progress } from 'mol-task';
  13. export interface StructureRepresentationComponentProps {
  14. viewer: Viewer
  15. representation: StructureRepresentation<StructureProps>
  16. }
  17. export interface StructureRepresentationComponentState {
  18. label: string
  19. visible: boolean
  20. alpha: number
  21. quality: VisualQuality
  22. colorTheme: ColorThemeProps
  23. resolutionFactor?: number
  24. probeRadius?: number
  25. isoValue?: number
  26. }
  27. export class StructureRepresentationComponent extends React.Component<StructureRepresentationComponentProps, StructureRepresentationComponentState> {
  28. state = {
  29. label: this.props.representation.label,
  30. visible: this.props.representation.props.visible,
  31. alpha: this.props.representation.props.alpha,
  32. quality: this.props.representation.props.quality,
  33. colorTheme: this.props.representation.props.colorTheme,
  34. resolutionFactor: (this.props.representation.props as any).resolutionFactor,
  35. probeRadius: (this.props.representation.props as any).probeRadius,
  36. isoValue: (this.props.representation.props as any).isoValue,
  37. }
  38. componentWillMount() {
  39. const repr = this.props.representation
  40. this.setState({
  41. ...this.state,
  42. label: repr.label,
  43. visible: repr.props.visible,
  44. alpha: repr.props.alpha,
  45. quality: repr.props.quality,
  46. colorTheme: repr.props.colorTheme,
  47. resolutionFactor: (repr.props as any).resolutionFactor,
  48. probeRadius: (repr.props as any).probeRadius,
  49. isoValue: (repr.props as any).isoValue,
  50. })
  51. }
  52. async update(state: Partial<StructureRepresentationComponentState>) {
  53. const repr = this.props.representation
  54. const props: Partial<StructureProps> = {}
  55. if (state.visible !== undefined) props.visible = state.visible
  56. if (state.quality !== undefined) props.quality = state.quality
  57. if (state.alpha !== undefined) props.alpha = state.alpha
  58. if (state.colorTheme !== undefined) props.colorTheme = state.colorTheme
  59. if (state.resolutionFactor !== undefined) (props as any).resolutionFactor = state.resolutionFactor
  60. if (state.probeRadius !== undefined) (props as any).probeRadius = state.probeRadius
  61. if (state.isoValue !== undefined) (props as any).isoValue = state.isoValue
  62. await repr.createOrUpdate(props).run(
  63. progress => console.log(Progress.format(progress)), 100
  64. )
  65. this.props.viewer.add(repr)
  66. this.props.viewer.draw(true)
  67. console.log(this.props.viewer.stats)
  68. console.log(
  69. 'drawCount',
  70. repr.renderObjects[0].values.drawCount.ref.version,
  71. repr.renderObjects[0].values.drawCount.ref.value,
  72. 'dColorType',
  73. repr.renderObjects[0].values.dColorType.ref.version,
  74. repr.renderObjects[0].values.dColorType.ref.value
  75. )
  76. const newState = {
  77. ...this.state,
  78. visible: repr.props.visible,
  79. quality: repr.props.quality,
  80. alpha: repr.props.alpha,
  81. colorTheme: repr.props.colorTheme,
  82. resolutionFactor: (repr.props as any).resolutionFactor,
  83. probeRadius: (repr.props as any).probeRadius,
  84. isoValue: (repr.props as any).isoValue,
  85. }
  86. this.setState(newState)
  87. }
  88. render() {
  89. const { label, visible, quality, alpha, colorTheme } = this.state
  90. const ct = ColorTheme(colorTheme)
  91. if (ct.legend && ct.legend.kind === 'scale-legend') {
  92. // console.log(`linear-gradient(to right, ${ct.legend.colors.map(c => Color.toStyle(c)).join(', ')})`)
  93. }
  94. return <div>
  95. <div>
  96. <h4>{label}</h4>
  97. </div>
  98. <div>
  99. <div>
  100. <span>Visible </span>
  101. <button onClick={(e) => this.update({ visible: !visible }) }>
  102. {visible ? 'Hide' : 'Show'}
  103. </button>
  104. </div>
  105. <div>
  106. <span>Quality </span>
  107. <select value={quality} onChange={(e) => this.update({ quality: e.target.value as VisualQuality }) }>
  108. {VisualQualityNames.map(name => <option key={name} value={name}>{name}</option>)}
  109. </select>
  110. </div>
  111. <div>
  112. <span>Opacity </span>
  113. <input type='range'
  114. defaultValue={alpha.toString()}
  115. min='0'
  116. max='1'
  117. step='0.05'
  118. onInput={(e) => this.update({ alpha: parseFloat(e.currentTarget.value) })}
  119. >
  120. </input>
  121. </div>
  122. { this.state.resolutionFactor !== undefined ? <div>
  123. <span>Resolution Factor </span>
  124. <input type='range'
  125. defaultValue={this.state.resolutionFactor.toString()}
  126. min='4'
  127. max='9'
  128. step='1'
  129. onInput={(e) => this.update({ resolutionFactor: parseInt(e.currentTarget.value) })}
  130. >
  131. </input>
  132. </div> : '' }
  133. { this.state.isoValue !== undefined ? <div>
  134. <span>Iso Value </span>
  135. <input type='range'
  136. defaultValue={this.state.isoValue.toString()}
  137. min='0.1'
  138. max='2'
  139. step='0.1'
  140. onInput={(e) => this.update({ isoValue: parseFloat(e.currentTarget.value) })}
  141. >
  142. </input>
  143. </div> : '' }
  144. { this.state.probeRadius !== undefined ? <div>
  145. <span>Probe Radius </span>
  146. <input type='range'
  147. defaultValue={this.state.probeRadius.toString()}
  148. min='0'
  149. max='10'
  150. step='0.1'
  151. onInput={(e) => this.update({ probeRadius: parseFloat(e.currentTarget.value) })}
  152. >
  153. </input>
  154. </div> : '' }
  155. <div>
  156. <span>Color Theme </span>
  157. <select value={colorTheme.name} onChange={(e) => this.update({ colorTheme: { name: e.target.value as ColorThemeName } }) }>
  158. {ColorThemeNames.map(name => <option key={name} value={name}>{name}</option>)}
  159. </select>
  160. {ct.description ? <div><i>{ct.description}</i></div> : ''}
  161. {
  162. ct.legend && ct.legend.kind === 'scale-legend'
  163. ? <div
  164. style={{
  165. width: '100%',
  166. height: '30px',
  167. background: `linear-gradient(to right, ${ct.legend.colors.map(c => Color.toStyle(c)).join(', ')})`
  168. }}
  169. >
  170. <span style={{float: 'left', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.min}</span>
  171. <span style={{float: 'right', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.max}</span>
  172. </div>
  173. : ct.legend && ct.legend.kind === 'table-legend'
  174. ? <div>
  175. {ct.legend.table.map((value, i) => {
  176. const [name, color] = value
  177. return <div key={i} style={{minWidth: '60px', marginRight: '5px', display: 'inline-block'}}>
  178. <div style={{width: '30px', height: '20px', backgroundColor: Color.toStyle(color), display: 'inline-block'}}></div>
  179. {name}
  180. </div>
  181. })}
  182. </div>
  183. : ''
  184. }
  185. </div>
  186. </div>
  187. </div>;
  188. }
  189. }