Ver Fonte

wip, canvas example

Alexander Rose há 6 anos atrás
pai
commit
655a0cf3e4

+ 2 - 2
src/apps/canvas/component/app.tsx

@@ -8,7 +8,7 @@ import * as React from 'react'
 import { StructureView } from '../structure-view';
 import { App } from '../app';
 import { Viewport } from './viewport';
-import { StructureComponent } from './structure';
+import { StructureViewComponent } from './structure-view';
 
 // export function FileInput (props: {
 //     accept: string
@@ -49,7 +49,7 @@ export class AppComponent extends React.Component<AppProps, AppState> {
             </div>
 
             <div style={{float: 'right', width: '25%', height: '100%'}}>
-                {structureView ? <StructureComponent structureView={structureView} /> : ''}
+                {structureView ? <StructureViewComponent structureView={structureView} /> : ''}
             </div>
         </div>;
     }

+ 70 - 0
src/apps/canvas/component/structure-representation.tsx

@@ -0,0 +1,70 @@
+/**
+ * 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 { StructureRepresentation, StructureProps } from 'mol-geo/representation/structure';
+import Viewer from 'mol-view/viewer';
+
+export interface StructureRepresentationComponentProps {
+    viewer: Viewer
+    representation: StructureRepresentation<StructureProps>
+}
+
+export interface StructureRepresentationComponentState {
+    label: string
+    visible: boolean
+}
+
+export class StructureRepresentationComponent extends React.Component<StructureRepresentationComponentProps, StructureRepresentationComponentState> {
+    state = {
+        label: this.props.representation.label,
+        visible: this.props.representation.props.visible,
+    }
+
+    componentWillMount() {
+        const repr = this.props.representation
+
+        this.setState({
+            ...this.state,
+            label: repr.label,
+            visible: repr.props.visible,
+        })
+    }
+
+    async update(state: Partial<StructureRepresentationComponentState>) {
+        const repr = this.props.representation
+
+        if (state.visible !== undefined) {
+            await repr.createOrUpdate({ visible: state.visible }).run()
+            // this.props.viewer.add(repr)
+            this.props.viewer.requestDraw()
+        }
+
+        const newState = {
+            ...this.state,
+            visible: repr.props.visible,
+        }
+        this.setState(newState)
+    }
+
+    render() {
+        const { label, visible } = this.state
+
+        return <div>
+            <div>
+                <h4>{label}</h4>
+            </div>
+            <div>
+                <div>
+                    <span>Visible</span>
+                    <button onClick={(e) => this.update({ visible: !visible }) }>
+                        {visible ? 'Hide' : 'Show'}
+                    </button>
+                </div>
+            </div>
+        </div>;
+    }
+}

+ 35 - 9
src/apps/canvas/component/structure.tsx → src/apps/canvas/component/structure-view.tsx

@@ -6,6 +6,8 @@
 
 import * as React from 'react'
 import { StructureView } from '../structure-view';
+import { StructureRepresentation } from 'mol-geo/representation/structure';
+import { StructureRepresentationComponent } from './structure-representation';
 
 // export function FileInput (props: {
 //     accept: string
@@ -18,11 +20,11 @@ import { StructureView } from '../structure-view';
 //     />
 // }
 
-export interface StructureComponentProps {
+export interface StructureViewComponentProps {
     structureView: StructureView
 }
 
-export interface StructureComponentState {
+export interface StructureViewComponentState {
     label: string
     modelId: number
     modelIds: { id: number, label: string }[]
@@ -30,9 +32,11 @@ export interface StructureComponentState {
     assemblyIds: { id: string, label: string }[]
     symmetryFeatureId: number
     symmetryFeatureIds: { id: number, label: string }[]
+
+    structureRepresentations: StructureRepresentation<any>[]
 }
 
-export class StructureComponent extends React.Component<StructureComponentProps, StructureComponentState> {
+export class StructureViewComponent extends React.Component<StructureViewComponentProps, StructureViewComponentState> {
     state = {
         label: this.props.structureView.label,
         modelId: this.props.structureView.modelId,
@@ -40,7 +44,9 @@ export class StructureComponent extends React.Component<StructureComponentProps,
         assemblyId: this.props.structureView.assemblyId,
         assemblyIds: this.props.structureView.getAssemblyIds(),
         symmetryFeatureId: this.props.structureView.symmetryFeatureId,
-        symmetryFeatureIds: this.props.structureView.getSymmetryFeatureIds()
+        symmetryFeatureIds: this.props.structureView.getSymmetryFeatureIds(),
+
+        structureRepresentations: this.props.structureView.structureRepresentations
     }
 
     componentWillMount() {
@@ -54,11 +60,19 @@ export class StructureComponent extends React.Component<StructureComponentProps,
             assemblyId: sv.assemblyId,
             assemblyIds: sv.getAssemblyIds(),
             symmetryFeatureId: sv.symmetryFeatureId,
-            symmetryFeatureIds: sv.getSymmetryFeatureIds()
+            symmetryFeatureIds: sv.getSymmetryFeatureIds(),
+
+            structureRepresentations: sv.structureRepresentations
         })
     }
 
-    async update(state: Partial<StructureComponentState>) {
+    componentDidMount() {
+        this.props.structureView.structureRepresentationsUpdated.subscribe(() => this.setState({
+            structureRepresentations: this.props.structureView.structureRepresentations
+        }))
+    }
+
+    async update(state: Partial<StructureViewComponentState>) {
         const sv = this.props.structureView
 
         if (state.modelId !== undefined) await sv.setModel(state.modelId)
@@ -73,13 +87,15 @@ export class StructureComponent extends React.Component<StructureComponentProps,
             assemblyId: sv.assemblyId,
             assemblyIds: sv.getAssemblyIds(),
             symmetryFeatureId: sv.symmetryFeatureId,
-            symmetryFeatureIds: sv.getSymmetryFeatureIds()
+            symmetryFeatureIds: sv.getSymmetryFeatureIds(),
+
+            structureRepresentations: sv.structureRepresentations
         }
         this.setState(newState)
     }
 
     render() {
-        const { label, modelIds, assemblyIds, symmetryFeatureIds } = this.state
+        const { label, modelIds, assemblyIds, symmetryFeatureIds, structureRepresentations } = this.state
 
         const modelIdOptions = modelIds.map(m => {
             return <option key={m.id} value={m.id}>{m.label}</option>
@@ -93,7 +109,7 @@ export class StructureComponent extends React.Component<StructureComponentProps,
 
         return <div>
             <div>
-                <span>{label}</span>
+                <h2>{label}</h2>
             </div>
             <div>
                 <div>
@@ -129,6 +145,16 @@ export class StructureComponent extends React.Component<StructureComponentProps,
                         {symmetryFeatureIdOptions}
                     </select>
                 </div>
+                <div>
+                    <h3>Structure Representations</h3>
+                    { structureRepresentations ? structureRepresentations.map((r, i) =>
+                        <div key={i}>
+                            <StructureRepresentationComponent
+                                representation={r}
+                                viewer={this.props.structureView.viewer}
+                            />
+                        </div>) : '' }
+                </div>
             </div>
         </div>;
     }

+ 36 - 50
src/apps/canvas/structure-view.ts

@@ -20,16 +20,19 @@ import { Color } from 'mol-util/color';
 import { computeUnitBoundary } from 'mol-model/structure/structure/util/boundary';
 import { addBoundingBox } from 'mol-geo/mesh/builder/bounding-box';
 import { PointRepresentation } from 'mol-geo/representation/structure/representation/point';
+import { StructureRepresentation } from 'mol-geo/representation/structure';
+import { BehaviorSubject } from 'rxjs';
 
 export interface StructureView {
+    readonly viewer: Viewer
+
     readonly label: string
     readonly models: ReadonlyArray<Model>
     readonly structure: Structure | undefined
     readonly assemblySymmetry: AssemblySymmetry | undefined
 
-    readonly cartoon: CartoonRepresentation
-    readonly ballAndStick: BallAndStickRepresentation
-    readonly carbohydrate: CarbohydrateRepresentation
+    readonly structureRepresentations: StructureRepresentation<any>[]
+    readonly structureRepresentationsUpdated: BehaviorSubject<null>
     readonly symmetryAxes: ShapeRepresentation<ShapeProps>
 
     readonly modelId: number
@@ -56,9 +59,19 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
     const point = PointRepresentation()
     const ballAndStick = BallAndStickRepresentation()
     const carbohydrate = CarbohydrateRepresentation()
+
+    const structureRepresentations: StructureRepresentation<any>[] = [
+        // cartoon,
+        point,
+        // ballAndStick,
+        // carbohydrate
+    ]
+
     const symmetryAxes = ShapeRepresentation()
     const polymerSphere = ShapeRepresentation()
 
+    const structureRepresentationsUpdated: BehaviorSubject<null> = new BehaviorSubject<null>(null)
+
     let label: string
     let model: Model | undefined
     let assemblySymmetry: AssemblySymmetry | undefined
@@ -156,29 +169,9 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
     async function createStructureRepr() {
         if (structure) {
             console.log('createStructureRepr')
-            await cartoon.createOrUpdate({
-                colorTheme: { name: 'chain-id' },
-                sizeTheme: { name: 'uniform', value: 0.2 },
-                useFog: false // TODO fog not working properly
-            }, structure).run()
-
-            // await point.createOrUpdate({
-            //     colorTheme: { name: 'unit-index' },
-            //     sizeTheme: { name: 'uniform', value: 0.2 },
-            //     useFog: false // TODO fog not working properly
-            // }, structure).run()
-
-            await ballAndStick.createOrUpdate({
-                colorTheme: { name: 'chain-id' },
-                sizeTheme: { name: 'uniform', value: 0.1 },
-                useFog: false // TODO fog not working properly
-            }, structure).run()
-
-            // await carbohydrate.createOrUpdate({
-            //     colorTheme: { name: 'carbohydrate-symbol' },
-            //     sizeTheme: { name: 'uniform', value: 1, factor: 1 },
-            //     useFog: false // TODO fog not working properly
-            // }, structure).run()
+            for (let i = 0, il = structureRepresentations.length; i < il; ++i) {
+                await structureRepresentations[i].createOrUpdate({}, structure).run()
+            }
 
             viewer.center(structure.boundary.sphere.center)
 
@@ -204,18 +197,13 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
             //     useFog: false // TODO fog not working properly
             // }, shape).run()
         } else {
-            cartoon.destroy()
-            point.destroy()
-            ballAndStick.destroy()
-            carbohydrate.destroy()
+            structureRepresentations.forEach(repr => repr.destroy)
             polymerSphere.destroy()
         }
 
-        viewer.add(cartoon)
-        viewer.add(point)
-        viewer.add(ballAndStick)
-        viewer.add(carbohydrate)
+        structureRepresentations.forEach(repr => viewer.add(repr))
         viewer.add(polymerSphere)
+        structureRepresentationsUpdated.next(null)
     }
 
     async function createSymmetryRepr() {
@@ -224,22 +212,18 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
             if (features._rowCount) {
                 const axesShape = getAxesShape(symmetryFeatureId, assemblySymmetry)
                 if (axesShape) {
-                    const colorTheme = getClusterColorTheme(symmetryFeatureId, assemblySymmetry)
+                    // const colorTheme = getClusterColorTheme(symmetryFeatureId, assemblySymmetry)
                     // await cartoon.createOrUpdate({
-                    //     colorTheme: { name: 'custom', ...colorTheme },
+                    //     colorTheme: { name: 'custom', color: colorTheme.color, granularity: colorTheme.granularity },
                     //     sizeTheme: { name: 'uniform', value: 0.2 },
                     //     useFog: false // TODO fog not working properly
                     // }).run()
                     // await ballAndStick.createOrUpdate({
-                    //     colorTheme:  { name: 'custom', ...colorTheme },
+                    //     colorTheme:  { name: 'custom', color: colorTheme.color, granularity: colorTheme.granularity },
                     //     sizeTheme: { name: 'uniform', value: 0.1 },
                     //     useFog: false // TODO fog not working properly
                     // }).run()
-                    await symmetryAxes.createOrUpdate({
-                        colorTheme: { name: 'shape-group', ...colorTheme },
-                        // colorTheme: { name: 'uniform', value: Color(0xFFCC22) },
-                        useFog: false // TODO fog not working properly
-                    }, axesShape).run()
+                    await symmetryAxes.createOrUpdate({}, axesShape).run()
                 } else {
                     symmetryAxes.destroy()
                 }
@@ -256,14 +240,15 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
     await setModel(0, props.assemblyId, props.symmetryFeatureId)
 
     return {
+        viewer,
+
         get label() { return label },
         models,
         get structure() { return structure },
         get assemblySymmetry() { return assemblySymmetry },
 
-        cartoon,
-        ballAndStick,
-        carbohydrate,
+        structureRepresentations,
+        structureRepresentationsUpdated,
         symmetryAxes,
 
         get modelId() { return modelId },
@@ -278,14 +263,15 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
         getSymmetryFeatureIds,
 
         destroy: () => {
-            viewer.remove(cartoon)
-            viewer.remove(ballAndStick)
-            viewer.remove(carbohydrate)
+            structureRepresentations.forEach(repr => {
+                viewer.remove(repr)
+                repr.destroy()
+            })
+            viewer.remove(polymerSphere)
             viewer.remove(symmetryAxes)
             viewer.requestDraw()
 
-            cartoon.destroy()
-            ballAndStick.destroy()
+            polymerSphere.destroy()
             symmetryAxes.destroy()
         }
     }