Browse Source

added assembly selector to render-test ui

Alexander Rose 7 years ago
parent
commit
7d8ef37094

+ 65 - 0
src/apps/render-test/components/assemblies.tsx

@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import * as React from 'react'
+import { WithStyles } from 'material-ui/styles';
+import { MenuItem } from 'material-ui/Menu';
+import { InputLabel } from 'material-ui/Input';
+import { FormControl } from 'material-ui/Form';
+import Select from 'material-ui/Select';
+
+import State from '../state'
+import Observer from './observer';
+import { Assembly } from 'mol-model/structure/model/properties/symmetry';
+
+interface AssemblyState {
+    loading: boolean
+    assemblies: ReadonlyArray<Assembly>
+    value: string
+}
+
+export default class Assemblies extends Observer<{ state: State } & WithStyles, AssemblyState> {
+    state: AssemblyState = { loading: false, assemblies: [], value: '' }
+
+    componentDidMount() {
+        this.subscribe(this.props.state.loading, value => {
+           this.setState({ loading: value });
+        });
+        this.subscribe(this.props.state.model, value => {
+            this.setState({ assemblies: value ? value.symmetry.assemblies : [] });
+        });
+        this.subscribe(this.props.state.assembly, value => {
+            this.setState({ value });
+        });
+    }
+
+    handleValueChange = (event: React.ChangeEvent<any>) => {
+        this.props.state.assembly.next(event.target.value)
+    }
+
+    render() {
+        const { classes } = this.props;
+
+        const items = this.state.assemblies.map((value, idx) => {
+            return <MenuItem key={idx} value={value.id}>{value.details}</MenuItem>
+        })
+
+        return <FormControl className={classes.formControl}>
+            <InputLabel htmlFor='assembly-value'>Assembly</InputLabel>
+            <Select
+                className={classes.selectField}
+                value={this.state.value}
+                onChange={this.handleValueChange}
+                inputProps={{
+                    name: 'value',
+                    id: 'assembly-value',
+                }}
+            >
+                {items}
+            </Select>
+        </FormControl>
+    }
+}

+ 1 - 1
src/apps/render-test/components/color-theme.tsx

@@ -22,7 +22,7 @@ interface ColorThemeState {
 }
 
 export default class ColorTheme extends Observer<{ state: State } & WithStyles, ColorThemeState> {
-    state = { loading: false, name: 'element-symbol' as _ColorTheme, value: 0xFF0000 }
+    state: ColorThemeState = { loading: false, name: 'element-symbol' as _ColorTheme, value: 0xFF0000 }
 
     componentDidMount() {
         this.subscribe(this.props.state.loading, value => {

+ 1 - 1
src/apps/render-test/components/detail.tsx

@@ -20,7 +20,7 @@ interface DetailState {
 }
 
 export default class Detail extends Observer<{ state: State } & WithStyles, DetailState> {
-    state = { loading: false, value: 2 }
+    state: DetailState = { loading: false, value: 2 }
 
     componentDidMount() {
         this.subscribe(this.props.state.loading, value => {

+ 1 - 1
src/apps/render-test/components/visibility.tsx

@@ -19,7 +19,7 @@ interface VisibilityState {
 }
 
 export default class Visibility extends Observer<{ state: State } & WithStyles, VisibilityState> {
-    state = { loading: false, spacefill: true, point: true }
+    state: VisibilityState = { loading: false, spacefill: true, point: true }
 
     componentDidMount() {
         this.subscribe(this.props.state.loading, value => {

+ 26 - 12
src/apps/render-test/state.ts

@@ -38,12 +38,14 @@ export type ColorTheme = keyof typeof ColorTheme
 export default class State {
     viewer: Viewer
     pdbId = '4cup'
+    model = new BehaviorSubject<Model | undefined>(undefined)
     initialized = new BehaviorSubject<boolean>(false)
     loading = new BehaviorSubject<boolean>(false)
 
     colorTheme = new BehaviorSubject<ColorTheme>('element-symbol')
     colorValue = new BehaviorSubject<Color>(0xFF4411)
     detail = new BehaviorSubject<number>(0)
+    assembly = new BehaviorSubject<string>('')
 
     pointVisibility = new BehaviorSubject<boolean>(true)
     spacefillVisibility = new BehaviorSubject<boolean>(true)
@@ -55,6 +57,7 @@ export default class State {
         this.colorTheme.subscribe(() => this.update())
         this.colorValue.subscribe(() => this.update())
         this.detail.subscribe(() => this.update())
+        this.assembly.subscribe(() => this.initStructure())
 
         this.pointVisibility.subscribe(() => this.updateVisibility())
         this.spacefillVisibility.subscribe(() => this.updateVisibility())
@@ -87,17 +90,28 @@ export default class State {
         this.viewer.animate()
     }
 
-    async initStructure (model: Model) {
-        const { viewer, loading } = this
-        viewer.clear()
-
+    async getStructure () {
+        const model = this.model.getValue()
+        if (!model) return
+        const assembly = this.assembly.getValue()
         let structure: Structure
         const assemblies = model.symmetry.assemblies
         if (assemblies.length) {
-            structure = await Run(Symmetry.buildAssembly(Structure.ofModel(model), '1'), log, 100)
+            structure = await Run(Symmetry.buildAssembly(Structure.ofModel(model), assembly || '1'), log, 100)
         } else {
             structure = Structure.ofModel(model)
         }
+        return structure
+    }
+
+    async initStructure () {
+        const { viewer, model } = this
+        if (!viewer || !model) return
+
+        viewer.clear()
+
+        const structure = await this.getStructure()
+        if (!structure) return
 
         this.pointRepr = StructureRepresentation(Point)
         await Run(this.pointRepr.create(structure, this.getPointProps()), log, 100)
@@ -110,25 +124,25 @@ export default class State {
         this.updateVisibility()
         viewer.requestDraw()
         console.log(viewer.stats)
+    }
 
-        loading.next(false)
+    setModel(model: Model) {
+        this.model.next(model)
+        this.initStructure()
+        this.loading.next(false)
     }
 
     async loadFile (file: File) {
         this.viewer.clear()
         this.loading.next(true)
-
-        const structures = await getModelFromFile(file)
-        this.initStructure(structures[0])
+        this.setModel((await getModelFromFile(file))[0])
     }
 
     async loadPdbId () {
         this.viewer.clear()
         if (this.pdbId.length !== 4) return
         this.loading.next(true)
-
-        const structures = await getModelFromPdbId(this.pdbId)
-        this.initStructure(structures[0])
+        this.setModel((await getModelFromPdbId(this.pdbId))[0])
     }
 
     async update () {

+ 2 - 0
src/apps/render-test/ui.tsx

@@ -18,6 +18,7 @@ import FileInput from './components/file-input'
 import ColorTheme from './components/color-theme'
 import Detail from './components/detail'
 import Visibility from './components/visibility'
+import Assemblies from './components/assemblies'
 
 
 const styles: StyleRulesCallback = (theme: Theme) => ({
@@ -83,6 +84,7 @@ class UI extends React.Component<{ state: State } & WithStyles, {  }> {
                     <FileInput state={state} classes={classes}></FileInput>
                     <form className={classes.root} autoComplete='off'>
                         <div>
+                            <Assemblies state={state} classes={classes}></Assemblies>
                             <ColorTheme state={state} classes={classes}></ColorTheme>
                             <Detail state={state} classes={classes}></Detail>
                             <Visibility state={state} classes={classes}></Visibility>