diff --git a/package-lock.json b/package-lock.json index 07548755dbc1dbc907eab692407d9650201d6438..a279c20acfa88ae56eeadb4587db80fba0f194f4 100644 Binary files a/package-lock.json and b/package-lock.json differ diff --git a/src/apps/canvas/app.ts b/src/apps/canvas/app.ts index ea0c7f2ff39c97c84fe68886d5bdb684417c5673..4da00cdbf9eb242a0913d7b8adbda6b922f53929 100644 --- a/src/apps/canvas/app.ts +++ b/src/apps/canvas/app.ts @@ -11,8 +11,7 @@ import { BehaviorSubject } from 'rxjs'; import { CifBlock } from 'mol-io/reader/cif'; import { volumeFromCcp4 } from 'mol-model/volume/formats/ccp4'; import { VolumeRepresentation } from 'mol-geo/representation/volume'; -import SurfaceVisual from 'mol-geo/representation/volume/surface'; -import { VolumeIsoValue } from 'mol-model/volume'; +import IsosurfaceVisual from 'mol-geo/representation/volume/isosurface'; export class App { viewer: Viewer @@ -88,9 +87,9 @@ export class App { const ccp4 = await getCcp4FromUrl(url) console.log(ccp4) const volume = await volumeFromCcp4(ccp4).run() - const volRepr = VolumeRepresentation(SurfaceVisual) + const volRepr = VolumeRepresentation(IsosurfaceVisual) await volRepr.createOrUpdate({ - isoValue: VolumeIsoValue.relative(volume.dataStats, 1) + isoValue: 1 }, volume).run() this.viewer.add(volRepr) console.log('volRepr', volRepr) diff --git a/src/apps/canvas/component/representation.tsx b/src/apps/canvas/component/representation.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5370036591b0eed7665b5a57693835e38cce753f --- /dev/null +++ b/src/apps/canvas/component/representation.tsx @@ -0,0 +1,49 @@ +/** + * 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 Viewer from 'mol-view/viewer'; +import { App } from '../app'; +import { Params } from 'mol-view/parameter'; +import { Representation } from 'mol-geo/representation'; +import { ParametersComponent } from 'mol-app/component/parameters'; + +export interface RepresentationComponentProps { + app: App + viewer: Viewer + repr: Representation<Params> +} + +export interface RepresentationComponentState { + +} + +export class RepresentationComponent extends React.Component<RepresentationComponentProps, RepresentationComponentState> { + + async onChange(k: string, v: any) { + await this.props.app.runTask(this.props.repr.createOrUpdate({ [k]: v }).run(), 'Representation Update') + this.props.viewer.add(this.props.repr) + this.props.viewer.requestDraw(true) + } + + render() { + const { repr } = this.props + // const ct = ColorTheme(colorTheme) + + return <div> + <div> + <h4>{repr.label}</h4> + </div> + <div> + <ParametersComponent + params={repr.params} + values={repr.props} + onChange={(k, v) => this.onChange(k as string, v)} + /> + </div> + </div>; + } +} \ No newline at end of file diff --git a/src/apps/canvas/component/structure-representation.tsx b/src/apps/canvas/component/structure-representation.tsx deleted file mode 100644 index 84ea120c157d99754dbc4f24c307b0a30cdeb6ff..0000000000000000000000000000000000000000 --- a/src/apps/canvas/component/structure-representation.tsx +++ /dev/null @@ -1,261 +0,0 @@ -/** - * 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'; -import { ColorThemeProps, ColorThemeName, ColorThemeNames, ColorTheme } from 'mol-view/theme/color'; -import { Color } from 'mol-util/color'; -import { Progress } from 'mol-task'; -import { VisualQuality, VisualQualityNames } from 'mol-geo/geometry/geometry'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { App } from '../app'; - -export interface StructureRepresentationComponentProps { - app: App - viewer: Viewer - representation: StructureRepresentation<StructureProps> -} - -export interface StructureRepresentationComponentState { - label: string - visible: boolean - alpha: number - quality: VisualQuality - colorTheme: ColorThemeProps - sizeTheme: SizeThemeProps - depthMask: boolean - - flatShaded?: boolean - resolutionFactor?: number - radiusOffset?: number - smoothness?: number - pointSizeAttenuation?: boolean - pointFilledCircle?: boolean - pointEdgeBleach?: number - - visuals?: { [k: string]: boolean } -} - -export class StructureRepresentationComponent extends React.Component<StructureRepresentationComponentProps, StructureRepresentationComponentState> { - state = this.stateFromRepresentation(this.props.representation) - - private stateFromRepresentation(repr: StructureRepresentation<StructureProps>) { - return { - label: repr.label, - visible: repr.props.visible, - alpha: repr.props.alpha, - quality: repr.props.quality, - colorTheme: repr.props.colorTheme, - sizeTheme: repr.props.sizeTheme, - depthMask: repr.props.depthMask, - - flatShaded: (repr.props as any).flatShaded, - resolutionFactor: (repr.props as any).resolutionFactor, - radiusOffset: (repr.props as any).radiusOffset, - smoothness: (repr.props as any).smoothness, - pointSizeAttenuation: (repr.props as any).pointSizeAttenuation, - pointFilledCircle: (repr.props as any).pointFilledCircle, - pointEdgeBleach: (repr.props as any).pointEdgeBleach, - - visuals: (repr.props as any).visuals, - } - } - - componentWillMount() { - this.setState(this.stateFromRepresentation(this.props.representation)) - } - - async update(state: Partial<StructureRepresentationComponentState>) { - const repr = this.props.representation - const props: Partial<StructureProps> = {} - - if (state.visible !== undefined) props.visible = state.visible - if (state.quality !== undefined) props.quality = state.quality - if (state.alpha !== undefined) props.alpha = state.alpha - if (state.colorTheme !== undefined) props.colorTheme = state.colorTheme - if (state.sizeTheme !== undefined) props.sizeTheme = state.sizeTheme - if (state.depthMask !== undefined) props.depthMask = state.depthMask - - if (state.flatShaded !== undefined) (props as any).flatShaded = state.flatShaded - if (state.resolutionFactor !== undefined) (props as any).resolutionFactor = state.resolutionFactor - if (state.radiusOffset !== undefined) (props as any).radiusOffset = state.radiusOffset - if (state.smoothness !== undefined) (props as any).smoothness = state.smoothness - if (state.pointSizeAttenuation !== undefined) (props as any).pointSizeAttenuation = state.pointSizeAttenuation - if (state.pointFilledCircle !== undefined) (props as any).pointFilledCircle = state.pointFilledCircle - if (state.pointEdgeBleach !== undefined) (props as any).pointEdgeBleach = state.pointEdgeBleach - - if (state.visuals !== undefined) (props as any).visuals = state.visuals - - await this.props.app.runTask(repr.createOrUpdate(props).run( - progress => console.log(Progress.format(progress)) - ), 'Create/update representation') - this.props.viewer.add(repr) - this.props.viewer.draw(true) - - this.setState(this.stateFromRepresentation(repr)) - } - - render() { - const { label, visible, quality, alpha, colorTheme, depthMask } = this.state - const ct = ColorTheme(colorTheme) - - return <div> - <div> - <h4>{label}</h4> - </div> - <div> - <div> - <span>Visible </span> - <button onClick={(e) => this.update({ visible: !visible }) }> - {visible ? 'Hide' : 'Show'} - </button> - </div> - { this.state.visuals !== undefined ? <div> - <span>Visuals: </span> - { Object.keys(this.state.visuals).map(k => { - return <span key={k}>{k} <input - type='checkbox' - checked={this.state.visuals[k]} - onChange={e => { - this.update({ visuals: { ...this.state.visuals, [k]: !!e.target.checked } }) - }} - ></input> </span> - }) } - </div> : '' } - <div> - <span>Depth Mask </span> - <button onClick={(e) => this.update({ depthMask: !depthMask }) }> - {depthMask ? 'Deactivate' : 'Activate'} - </button> - </div> - { this.state.flatShaded !== undefined ? <div> - <span>Flat Shaded </span> - <button onClick={(e) => this.update({ flatShaded: !this.state.flatShaded }) }> - {this.state.flatShaded ? 'Deactivate' : 'Activate'} - </button> - </div> : '' } - <div> - <span>Quality </span> - <select value={quality} onChange={e => this.update({ quality: e.target.value as VisualQuality }) }> - {VisualQualityNames.map(name => <option key={name} value={name}>{name}</option>)} - </select> - </div> - <div> - <span>Opacity </span> - <input type='range' - defaultValue={alpha.toString()} - min='0' - max='1' - step='0.05' - onInput={e => this.update({ alpha: parseFloat(e.currentTarget.value) })} - > - </input> - </div> - { this.state.resolutionFactor !== undefined ? <div> - <span>Resolution Factor </span> - <input type='range' - defaultValue={this.state.resolutionFactor.toString()} - min='4' - max='9' - step='1' - onChange={(e) => this.update({ resolutionFactor: parseInt(e.currentTarget.value) })} - > - </input> - </div> : '' } - { this.state.smoothness !== undefined ? <div> - <span>Smoothness </span> - <input type='range' - defaultValue={this.state.smoothness.toString()} - min='1' - max='3' - step='0.1' - onChange={e => this.update({ smoothness: parseFloat(e.currentTarget.value) })} - > - </input> - </div> : '' } - { this.state.radiusOffset !== undefined ? <div> - <span>Radius Offset </span> - <input type='range' - defaultValue={this.state.radiusOffset.toString()} - min='0' - max='4' - step='0.1' - onChange={e => this.update({ radiusOffset: parseFloat(e.currentTarget.value) })} - > - </input> - </div> : '' } - { this.state.pointSizeAttenuation !== undefined ? <div> - <span>Size Attenuation </span> - <button onClick={e => this.update({ pointSizeAttenuation: !this.state.pointSizeAttenuation }) }> - {this.state.pointSizeAttenuation ? 'Deactivate' : 'Activate'} - </button> - </div> : '' } - { this.state.pointFilledCircle !== undefined ? <div> - <span>Filled Circle </span> - <button onClick={e => this.update({ pointFilledCircle: !this.state.pointFilledCircle }) }> - {this.state.pointFilledCircle ? 'Deactivate' : 'Activate'} - </button> - </div> : '' } - { this.state.pointEdgeBleach !== undefined ? <div> - <span>Edge Bleach </span> - <input type='range' - defaultValue={this.state.pointEdgeBleach.toString()} - min='0' - max='1' - step='0.05' - onInput={e => this.update({ pointEdgeBleach: parseFloat(e.currentTarget.value) })} - > - </input> - </div> : '' } - { this.state.sizeTheme !== undefined && this.state.sizeTheme.name === 'uniform' ? <div> - <span>Uniform Size </span> - <input type='range' - defaultValue={this.state.sizeTheme.value!.toString()} - min='0' - max='10' - step='0.1' - onInput={e => this.update({ - sizeTheme: { name: 'uniform', value: parseFloat(e.currentTarget.value) } - })} - > - </input> - </div> : '' } - <div> - <span>Color Theme </span> - <select value={colorTheme.name} onChange={e => this.update({ colorTheme: { name: e.target.value as ColorThemeName } }) }> - {ColorThemeNames.map(name => <option key={name} value={name}>{name}</option>)} - </select> - {ct.description ? <div><i>{ct.description}</i></div> : ''} - { - ct.legend && ct.legend.kind === 'scale-legend' - ? <div - style={{ - width: '100%', - height: '30px', - background: `linear-gradient(to right, ${ct.legend.colors.map(c => Color.toStyle(c)).join(', ')})` - }} - > - <span style={{float: 'left', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.minLabel}</span> - <span style={{float: 'right', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.maxLabel}</span> - </div> - : ct.legend && ct.legend.kind === 'table-legend' - ? <div> - {ct.legend.table.map((value, i) => { - const [name, color] = value - return <div key={i} style={{minWidth: '60px', marginRight: '5px', display: 'inline-block'}}> - <div style={{width: '30px', height: '20px', backgroundColor: Color.toStyle(color), display: 'inline-block'}}></div> - {name} - </div> - })} - </div> - : '' - } - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/apps/canvas/component/structure-view.tsx b/src/apps/canvas/component/structure-view.tsx index 82ca7a29d46acbbeafbc3496ffb6a31e91ae0829..91bbe6cc93365ccf4ab00706fcbfa016ee148205 100644 --- a/src/apps/canvas/component/structure-view.tsx +++ b/src/apps/canvas/component/structure-view.tsx @@ -7,7 +7,8 @@ import * as React from 'react' import { StructureView } from '../structure-view'; import { StructureRepresentation } from 'mol-geo/representation/structure'; -import { StructureRepresentationComponent } from './structure-representation'; +import { RepresentationComponent } from './representation'; +import { Representation } from 'mol-geo/representation'; // export function FileInput (props: { // accept: string @@ -182,8 +183,8 @@ export class StructureViewComponent extends React.Component<StructureViewCompone { Object.keys(structureRepresentations).map((k, i) => { if (active[k]) { return <div key={i}> - <StructureRepresentationComponent - representation={structureRepresentations[k]} + <RepresentationComponent + repr={structureRepresentations[k] as Representation<any>} viewer={structureView.viewer} app={structureView.app} /> diff --git a/src/apps/canvas/component/volume-representation.tsx b/src/apps/canvas/component/volume-representation.tsx deleted file mode 100644 index b22b95667622e931c0cbf5047c554fbcbe23ef0b..0000000000000000000000000000000000000000 --- a/src/apps/canvas/component/volume-representation.tsx +++ /dev/null @@ -1,245 +0,0 @@ -/** - * 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 Viewer from 'mol-view/viewer'; -import { ColorThemeProps, ColorThemeName, ColorThemeNames, ColorTheme } from 'mol-view/theme/color'; -import { Color } from 'mol-util/color'; -import { Progress } from 'mol-task'; -import { VisualQuality, VisualQualityNames } from 'mol-geo/geometry/geometry'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { App } from '../app'; -import { VolumeRepresentation, VolumeProps } from 'mol-geo/representation/volume'; - -export interface VolumeRepresentationComponentProps { - app: App - viewer: Viewer - representation: VolumeRepresentation<VolumeProps> -} - -export interface VolumeRepresentationComponentState { - label: string - visible: boolean - alpha: number - quality: VisualQuality - colorTheme: ColorThemeProps - depthMask: boolean - - flatShaded?: boolean - resolutionFactor?: number - radiusOffset?: number - smoothness?: number - pointSizeAttenuation?: boolean - pointFilledCircle?: boolean - pointEdgeBleach?: number - - visuals?: { [k: string]: boolean } -} - -export class VolumeRepresentationComponent extends React.Component<VolumeRepresentationComponentProps, VolumeRepresentationComponentState> { - state = this.stateFromRepresentation(this.props.representation) - - private stateFromRepresentation(repr: VolumeRepresentation<VolumeProps>) { - return { - label: repr.label, - visible: repr.props.visible, - alpha: repr.props.alpha, - quality: repr.props.quality, - colorTheme: repr.props.colorTheme, - depthMask: repr.props.depthMask, - - flatShaded: (repr.props as any).flatShaded, - resolutionFactor: (repr.props as any).resolutionFactor, - radiusOffset: (repr.props as any).radiusOffset, - smoothness: (repr.props as any).smoothness, - pointSizeAttenuation: (repr.props as any).pointSizeAttenuation, - pointFilledCircle: (repr.props as any).pointFilledCircle, - pointEdgeBleach: (repr.props as any).pointEdgeBleach, - - visuals: (repr.props as any).visuals, - } - } - - componentWillMount() { - this.setState(this.stateFromRepresentation(this.props.representation)) - } - - async update(state: Partial<VolumeRepresentationComponentState>) { - const repr = this.props.representation - const props: Partial<VolumeProps> = {} - - if (state.visible !== undefined) props.visible = state.visible - if (state.quality !== undefined) props.quality = state.quality - if (state.alpha !== undefined) props.alpha = state.alpha - if (state.colorTheme !== undefined) props.colorTheme = state.colorTheme - if (state.depthMask !== undefined) props.depthMask = state.depthMask - - if (state.flatShaded !== undefined) (props as any).flatShaded = state.flatShaded - if (state.resolutionFactor !== undefined) (props as any).resolutionFactor = state.resolutionFactor - if (state.radiusOffset !== undefined) (props as any).radiusOffset = state.radiusOffset - if (state.smoothness !== undefined) (props as any).smoothness = state.smoothness - if (state.pointSizeAttenuation !== undefined) (props as any).pointSizeAttenuation = state.pointSizeAttenuation - if (state.pointFilledCircle !== undefined) (props as any).pointFilledCircle = state.pointFilledCircle - if (state.pointEdgeBleach !== undefined) (props as any).pointEdgeBleach = state.pointEdgeBleach - - if (state.visuals !== undefined) (props as any).visuals = state.visuals - - await this.props.app.runTask(repr.createOrUpdate(props).run( - progress => console.log(Progress.format(progress)) - ), 'Create/update representation') - this.props.viewer.add(repr) - this.props.viewer.draw(true) - - this.setState(this.stateFromRepresentation(repr)) - } - - render() { - const { label, visible, quality, alpha, colorTheme, depthMask } = this.state - const ct = ColorTheme(colorTheme) - - return <div> - <div> - <h4>{label}</h4> - </div> - <div> - <div> - <span>Visible </span> - <button onClick={(e) => this.update({ visible: !visible }) }> - {visible ? 'Hide' : 'Show'} - </button> - </div> - { this.state.visuals !== undefined ? <div> - <span>Visuals: </span> - { Object.keys(this.state.visuals).map(k => { - return <span key={k}>{k} <input - type='checkbox' - checked={this.state.visuals[k]} - onChange={e => { - this.update({ visuals: { ...this.state.visuals, [k]: !!e.target.checked } }) - }} - ></input> </span> - }) } - </div> : '' } - <div> - <span>Depth Mask </span> - <button onClick={(e) => this.update({ depthMask: !depthMask }) }> - {depthMask ? 'Deactivate' : 'Activate'} - </button> - </div> - { this.state.flatShaded !== undefined ? <div> - <span>Flat Shaded </span> - <button onClick={(e) => this.update({ flatShaded: !this.state.flatShaded }) }> - {this.state.flatShaded ? 'Deactivate' : 'Activate'} - </button> - </div> : '' } - <div> - <span>Quality </span> - <select value={quality} onChange={e => this.update({ quality: e.target.value as VisualQuality }) }> - {VisualQualityNames.map(name => <option key={name} value={name}>{name}</option>)} - </select> - </div> - <div> - <span>Opacity </span> - <input type='range' - defaultValue={alpha.toString()} - min='0' - max='1' - step='0.05' - onInput={e => this.update({ alpha: parseFloat(e.currentTarget.value) })} - > - </input> - </div> - { this.state.resolutionFactor !== undefined ? <div> - <span>Resolution Factor </span> - <input type='range' - defaultValue={this.state.resolutionFactor.toString()} - min='4' - max='9' - step='1' - onChange={(e) => this.update({ resolutionFactor: parseInt(e.currentTarget.value) })} - > - </input> - </div> : '' } - { this.state.smoothness !== undefined ? <div> - <span>Smoothness </span> - <input type='range' - defaultValue={this.state.smoothness.toString()} - min='1' - max='3' - step='0.1' - onChange={e => this.update({ smoothness: parseFloat(e.currentTarget.value) })} - > - </input> - </div> : '' } - { this.state.radiusOffset !== undefined ? <div> - <span>Radius Offset </span> - <input type='range' - defaultValue={this.state.radiusOffset.toString()} - min='0' - max='4' - step='0.1' - onChange={e => this.update({ radiusOffset: parseFloat(e.currentTarget.value) })} - > - </input> - </div> : '' } - { this.state.pointSizeAttenuation !== undefined ? <div> - <span>Size Attenuation </span> - <button onClick={e => this.update({ pointSizeAttenuation: !this.state.pointSizeAttenuation }) }> - {this.state.pointSizeAttenuation ? 'Deactivate' : 'Activate'} - </button> - </div> : '' } - { this.state.pointFilledCircle !== undefined ? <div> - <span>Filled Circle </span> - <button onClick={e => this.update({ pointFilledCircle: !this.state.pointFilledCircle }) }> - {this.state.pointFilledCircle ? 'Deactivate' : 'Activate'} - </button> - </div> : '' } - { this.state.pointEdgeBleach !== undefined ? <div> - <span>Edge Bleach </span> - <input type='range' - defaultValue={this.state.pointEdgeBleach.toString()} - min='0' - max='1' - step='0.05' - onInput={e => this.update({ pointEdgeBleach: parseFloat(e.currentTarget.value) })} - > - </input> - </div> : '' } - <div> - <span>Color Theme </span> - <select value={colorTheme.name} onChange={e => this.update({ colorTheme: { name: e.target.value as ColorThemeName } }) }> - {ColorThemeNames.map(name => <option key={name} value={name}>{name}</option>)} - </select> - {ct.description ? <div><i>{ct.description}</i></div> : ''} - { - ct.legend && ct.legend.kind === 'scale-legend' - ? <div - style={{ - width: '100%', - height: '30px', - background: `linear-gradient(to right, ${ct.legend.colors.map(c => Color.toStyle(c)).join(', ')})` - }} - > - <span style={{float: 'left', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.minLabel}</span> - <span style={{float: 'right', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.maxLabel}</span> - </div> - : ct.legend && ct.legend.kind === 'table-legend' - ? <div> - {ct.legend.table.map((value, i) => { - const [name, color] = value - return <div key={i} style={{minWidth: '60px', marginRight: '5px', display: 'inline-block'}}> - <div style={{width: '30px', height: '20px', backgroundColor: Color.toStyle(color), display: 'inline-block'}}></div> - {name} - </div> - })} - </div> - : '' - } - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/apps/canvas/index.ts b/src/apps/canvas/index.ts index 76e32dee292221aa544ec2a4a4d912696399b5a8..b02f1c33fb14b4b5942ea0ab9e4fa00a960749c4 100644 --- a/src/apps/canvas/index.ts +++ b/src/apps/canvas/index.ts @@ -23,4 +23,4 @@ const assemblyId = urlQueryParameter('assembly') const pdbId = urlQueryParameter('pdb') if (pdbId) app.loadPdbIdOrMmcifUrl(pdbId, { assemblyId }) -app.loadCcp4File() \ No newline at end of file +// app.loadCcp4File() \ No newline at end of file diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts index 1f0d7149f9e1448b31bc362619ad84299b2cf198..4224874470d1465db4880d83f58f226d5ee3fe25 100644 --- a/src/apps/canvas/structure-view.ts +++ b/src/apps/canvas/structure-view.ts @@ -24,7 +24,7 @@ import { StructureRepresentation } from 'mol-geo/representation/structure'; import { BehaviorSubject } from 'rxjs'; import { SpacefillRepresentation } from 'mol-geo/representation/structure/representation/spacefill'; import { DistanceRestraintRepresentation } from 'mol-geo/representation/structure/representation/distance-restraint'; -import { SurfaceRepresentation } from 'mol-geo/representation/structure/representation/surface'; +import { MolecularSurfaceRepresentation } from 'mol-geo/representation/structure/representation/molecular-surface'; import { App } from './app'; import { Progress } from 'mol-task'; @@ -81,7 +81,7 @@ export async function StructureView(app: App, viewer: Viewer, models: ReadonlyAr const structureRepresentations: { [k: string]: StructureRepresentation<any> } = { cartoon: CartoonRepresentation(), - surface: SurfaceRepresentation(), + surface: MolecularSurfaceRepresentation(), point: PointRepresentation(), ballAndStick: BallAndStickRepresentation(), carbohydrate: CarbohydrateRepresentation(), diff --git a/src/apps/structure-info/volume.ts b/src/apps/structure-info/volume.ts index 00dd391711eba424686f5825594056426ac04380..2f5e6441f3c4a563089e9ff56df85a0c17fd6f4f 100644 --- a/src/apps/structure-info/volume.ts +++ b/src/apps/structure-info/volume.ts @@ -13,7 +13,7 @@ import { downloadCif } from './helpers' import CIF from 'mol-io/reader/cif' import { DensityServer_Data_Database } from 'mol-io/reader/cif/schema/density-server'; import { Table } from 'mol-data/db'; -import { computeVolumeSurface } from 'mol-geo/representation/volume/surface'; +import { computeVolumeSurface } from 'mol-geo/representation/volume/isosurface'; import { StringBuilder } from 'mol-util'; require('util.promisify').shim(); diff --git a/src/apps/viewer/index.html b/src/apps/viewer/index.html deleted file mode 100644 index b2c505caf8929418a0dbe3e3107fd945179a6855..0000000000000000000000000000000000000000 --- a/src/apps/viewer/index.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> - <title>Mol* Viewer</title> - <link href='./app.css', rel="stylesheet"> - </head> - <body> - <div id="app"></div> - <script type="text/javascript" src="./index.js"></script> - </body> -</html> \ No newline at end of file diff --git a/src/apps/viewer/index.tsx b/src/apps/viewer/index.tsx deleted file mode 100644 index 26be8a64a8739850f7e00e9d9961130fec970066..0000000000000000000000000000000000000000 --- a/src/apps/viewer/index.tsx +++ /dev/null @@ -1,107 +0,0 @@ -/** - * 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 * as ReactDOM from 'react-dom' - -import './index.html' -import 'mol-app/skin/molstar-light.scss' - -import { Context } from 'mol-app/context/context'; -import { Viewport } from 'mol-app/ui/visualization/viewport' -import { makeEmptyTargets, LayoutRegion } from 'mol-app/controller/layout'; -import { Layout } from 'mol-app/ui/layout'; -import { LogController } from 'mol-app/controller/misc/log'; -import { Log } from 'mol-app/ui/misc/log'; -import { JobsController } from 'mol-app/controller/misc/jobs'; -import { BackgroundJobs, Overlay } from 'mol-app/ui/misc/jobs'; -import { EntityTree } from 'mol-app/ui/entity/tree'; -import { EntityTreeController } from 'mol-app/controller/entity/tree'; -import { TransformListController } from 'mol-app/controller/transform/list'; -import { TransformList } from 'mol-app/ui/transform/list'; -import { SequenceView } from 'mol-app/ui/visualization/sequence-view'; -import { InteractivityEvents } from 'mol-app/event/basic'; -import { MarkerAction } from 'mol-geo/geometry/marker-data'; -import { EveryLoci } from 'mol-model/loci'; - -const elm = document.getElementById('app') -if (!elm) throw new Error('Can not find element with id "app".') - -const ctx = new Context() -const targets = makeEmptyTargets(); - -targets[LayoutRegion.Main].components.push({ - key: 'molstar-internal-viewport', - controller: ctx.viewport, - region: LayoutRegion.Main, - view: Viewport, - isStatic: true -}); - -targets[LayoutRegion.Bottom].components.push({ - key: 'molstar-log', - controller: new LogController(ctx), - region: LayoutRegion.Bottom, - view: Log, - isStatic: true -}); - -targets[LayoutRegion.Top].components.push({ - key: 'molstar-sequence-view', - controller: ctx.components.sequenceView, - region: LayoutRegion.Top, - view: SequenceView, - isStatic: true -}); - -targets[LayoutRegion.Main].components.push({ - key: 'molstar-background-jobs', - controller: new JobsController(ctx, 'Background'), - region: LayoutRegion.Main, - view: BackgroundJobs, - isStatic: true -}); - -targets[LayoutRegion.Root].components.push({ - key: 'molstar-overlay', - controller: new JobsController(ctx, 'Normal'), - region: LayoutRegion.Root, - view: Overlay, - isStatic: true -}); - -targets[LayoutRegion.Right].components.push({ - key: 'molstar-transform-list', - controller: new TransformListController(ctx), - region: LayoutRegion.Right, - view: TransformList, - isStatic: false -}); - -targets[LayoutRegion.Left].components.push({ - key: 'molstar-entity-tree', - controller: new EntityTreeController(ctx), - region: LayoutRegion.Left, - view: EntityTree, - isStatic: true -}); - -ctx.createLayout(targets, elm) -ctx.layout.setState({ - isExpanded: true, - hideControls: false, - collapsedControlsLayout: 0 -}) -// ctx.viewport.setState() - -ctx.dispatcher.getStream(InteractivityEvents.HighlightLoci).subscribe(event => { - ctx.stage.viewer.mark(EveryLoci, MarkerAction.RemoveHighlight) - if (event && event.data) { - ctx.stage.viewer.mark(event.data, MarkerAction.Highlight) - } -}) - -ReactDOM.render(React.createElement(Layout, { controller: ctx.layout }), elm); diff --git a/src/mol-app/component/color-theme.tsx b/src/mol-app/component/color-theme.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1df6a6b383fbef71dd83b9d718f0673f356e5c2e --- /dev/null +++ b/src/mol-app/component/color-theme.tsx @@ -0,0 +1,56 @@ +/** + * 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 { ColorTheme } from 'mol-view/theme/color'; +import { Color } from 'mol-util/color'; + +export interface ColorThemeComponentProps { + colorTheme: ColorTheme +} + +export interface ColorThemeComponentState { + +} + +export class ColorThemeComponent extends React.Component<ColorThemeComponentProps, ColorThemeComponentState> { + state = { + + } + + render() { + const ct = this.props.colorTheme + return <div> + <span>Color Theme </span> + + {ct.description ? <div><i>{ct.description}</i></div> : ''} + { + ct.legend && ct.legend.kind === 'scale-legend' + ? <div + style={{ + width: '100%', + height: '30px', + background: `linear-gradient(to right, ${ct.legend.colors.map(c => Color.toStyle(c)).join(', ')})` + }} + > + <span style={{float: 'left', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.minLabel}</span> + <span style={{float: 'right', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.maxLabel}</span> + </div> + : ct.legend && ct.legend.kind === 'table-legend' + ? <div> + {ct.legend.table.map((value, i) => { + const [name, color] = value + return <div key={i} style={{minWidth: '60px', marginRight: '5px', display: 'inline-block'}}> + <div style={{width: '30px', height: '20px', backgroundColor: Color.toStyle(color), display: 'inline-block'}}></div> + {name} + </div> + })} + </div> + : '' + } + </div>; + } +} \ No newline at end of file diff --git a/src/mol-app/component/parameter/boolean.tsx b/src/mol-app/component/parameter/boolean.tsx new file mode 100644 index 0000000000000000000000000000000000000000..997b2ca5c42da85f838cd07bda3e2d1edb6d019a --- /dev/null +++ b/src/mol-app/component/parameter/boolean.tsx @@ -0,0 +1,38 @@ +/** + * 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 { BooleanParam } from 'mol-view/parameter'; + +export interface BooleanParamComponentProps { + param: BooleanParam + value: boolean + onChange(v: boolean): void +} + +export interface BooleanParamComponentState { + value: boolean +} + +export class BooleanParamComponent extends React.Component<BooleanParamComponentProps, BooleanParamComponentState> { + state = { + value: this.props.value + } + + onChange(value: boolean) { + this.setState({ value }) + this.props.onChange(value) + } + + render() { + return <div> + <span>{this.props.param.label} </span> + <button onClick={e => this.onChange(!this.state.value) }> + {this.state.value ? 'Off' : 'On'} + </button> + </div>; + } +} \ No newline at end of file diff --git a/src/mol-app/component/parameter/number.tsx b/src/mol-app/component/parameter/number.tsx new file mode 100644 index 0000000000000000000000000000000000000000..be97aee26f79de663689de062c0fecdc912e9291 --- /dev/null +++ b/src/mol-app/component/parameter/number.tsx @@ -0,0 +1,44 @@ +/** + * 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 { NumberParam } from 'mol-view/parameter'; + +export interface NumberParamComponentProps { + param: NumberParam + value: number + onChange(v: number): void +} + +export interface NumberParamComponentState { + value: number +} + +export class NumberParamComponent extends React.Component<NumberParamComponentProps, NumberParamComponentState> { + state = { + value: this.props.value + } + + onChange(valueStr: string) { + const value = Number.isInteger(this.props.param.step) ? parseInt(valueStr) : parseFloat(valueStr) + this.setState({ value }) + this.props.onChange(value) + } + + render() { + return <div> + <span>{this.props.param.label} </span> + <input type='range' + value={this.state.value} + min={this.props.param.min} + max={this.props.param.max} + step={this.props.param.step} + onChange={e => this.onChange(e.currentTarget.value)} + > + </input> + </div>; + } +} \ No newline at end of file diff --git a/src/mol-app/component/parameter/range.tsx b/src/mol-app/component/parameter/range.tsx new file mode 100644 index 0000000000000000000000000000000000000000..dd9c82fa236d6d6d62a7092c50fccb8d4c725dad --- /dev/null +++ b/src/mol-app/component/parameter/range.tsx @@ -0,0 +1,44 @@ +/** + * 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 { RangeParam } from 'mol-view/parameter'; + +export interface RangeParamComponentProps { + param: RangeParam + value: number + onChange(v: number): void +} + +export interface RangeParamComponentState { + value: number +} + +export class RangeParamComponent extends React.Component<RangeParamComponentProps, RangeParamComponentState> { + state = { + value: this.props.value + } + + onChange(valueStr: string) { + const value = Number.isInteger(this.props.param.step) ? parseInt(valueStr) : parseFloat(valueStr) + this.setState({ value }) + this.props.onChange(value) + } + + render() { + return <div> + <span>{this.props.param.label} </span> + <input type='range' + value={this.state.value} + min={this.props.param.min} + max={this.props.param.max} + step={this.props.param.step} + onChange={e => this.onChange(e.currentTarget.value)} + > + </input> + </div>; + } +} \ No newline at end of file diff --git a/src/mol-app/component/parameter/select.tsx b/src/mol-app/component/parameter/select.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e403bbb79f2cd56c9dbf5e878e7f41229d317012 --- /dev/null +++ b/src/mol-app/component/parameter/select.tsx @@ -0,0 +1,41 @@ +/** + * 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 { SelectParam } from 'mol-view/parameter'; + +export interface SelectParamComponentProps<T extends string> { + param: SelectParam<T> + value: T + onChange(v: T): void +} + +export interface SelectParamComponentState<T extends string> { + value: T +} + +export class SelectParamComponent<T extends string> extends React.Component<SelectParamComponentProps<T>, SelectParamComponentState<T>> { + state = { + value: this.props.value + } + + onChange(value: T) { + this.setState({ value }) + this.props.onChange(value) + } + + render() { + return <div> + <span>{this.props.param.label} </span> + <select value={this.state.value} onChange={e => this.onChange(e.target.value as T) }> + {this.props.param.options.map(v => { + const [value, label] = v + return <option key={label} value={value}>{label}</option> + })} + </select> + </div>; + } +} \ No newline at end of file diff --git a/src/mol-app/component/parameters.tsx b/src/mol-app/component/parameters.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d5446e33cba28cd5a68bdd38a3e5fd8ed52425d3 --- /dev/null +++ b/src/mol-app/component/parameters.tsx @@ -0,0 +1,52 @@ +/** + * 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 { Param, Params } from 'mol-view/parameter'; +import { BooleanParamComponent } from './parameter/boolean'; +import { NumberParamComponent } from './parameter/number'; +import { RangeParamComponent } from './parameter/range'; +import { SelectParamComponent } from './parameter/select'; + +interface ParametersProps<P extends Params> { + params: P + values: { [k in keyof P]: P[k]['defaultValue'] } + onChange<K extends keyof P>(k: K, v: P[K]['defaultValue']): void +} + +type ParametersState = {} + +function getParamComponent<P extends Param>(p: Param, value: P['defaultValue'], onChange: (v: P['defaultValue']) => void) { + switch (p.type) { + case 'boolean': + return <BooleanParamComponent param={p} value={value} onChange={onChange} /> + case 'number': + return <NumberParamComponent param={p} value={value} onChange={onChange} /> + case 'range': + return <RangeParamComponent param={p} value={value} onChange={onChange} /> + case 'select': + return <SelectParamComponent param={p} value={value} onChange={onChange} /> + } + return '' +} + +export class ParametersComponent<P extends Params> extends React.Component<ParametersProps<P>, ParametersState> { + onChange(k: string, value: any) { + this.props.onChange(k, value) + } + + render() { + return <div> + { Object.keys(this.props.params).map(k => { + const param = this.props.params[k] + const value = this.props.values[k] + return <div key={k}> + {getParamComponent(param, value, v => this.onChange(k, v))} + </div> + })} + </div>; + } +} \ No newline at end of file diff --git a/src/mol-app/component/sequence.tsx b/src/mol-app/component/sequence.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f90039eb36161b1eb8c71e0f6dc3aebe99d6d6f9 --- /dev/null +++ b/src/mol-app/component/sequence.tsx @@ -0,0 +1,81 @@ +// /** +// * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. +// * +// * @author David Sehnal <david.sehnal@gmail.com> +// */ + +// import * as React from 'react' +// import { Structure, StructureSequence, Queries, StructureSelection, StructureProperties, StructureQuery } from 'mol-model/structure'; +// import { EmptyLoci } from 'mol-model/loci'; + +// export class SequenceView extends View<SequenceViewController, {}, {}> { +// render() { +// const s = this.controller.latestState.structure; +// if (!s) return <div className='molstar-sequence-view-wrap'>No structure available.</div>; + +// const seqs = s.models[0].sequence.sequences; +// return <div className='molstar-sequence-view-wrap'> +// {seqs.map((seq, i) => <EntitySequence key={i} ctx={this.controller.context} seq={seq} structure={s} /> )} +// </div>; +// } +// } + +// function createQuery(entityId: string, label_seq_id: number) { +// return Queries.generators.atoms({ +// entityTest: ctx => StructureProperties.entity.id(ctx.element) === entityId, +// residueTest: ctx => StructureProperties.residue.label_seq_id(ctx.element) === label_seq_id +// }); +// } + +// // TODO: this is really ineffective and should be done using a canvas. +// class EntitySequence extends React.Component<{ ctx: Context, seq: StructureSequence.Entity, structure: Structure }> { + +// raiseInteractityEvent(seqId?: number) { +// if (typeof seqId === 'undefined') { +// InteractivityEvents.HighlightLoci.dispatch(this.props.ctx, EmptyLoci); +// return; +// } + +// const query = createQuery(this.props.seq.entityId, seqId); +// const loci = StructureSelection.toLoci(StructureQuery.run(query, this.props.structure)); +// if (loci.elements.length === 0) InteractivityEvents.HighlightLoci.dispatch(this.props.ctx, EmptyLoci); +// else InteractivityEvents.HighlightLoci.dispatch(this.props.ctx, loci); +// } + + +// render() { +// const { ctx, seq } = this.props; +// const { offset, sequence } = seq.sequence; + +// const elems: JSX.Element[] = []; +// for (let i = 0, _i = sequence.length; i < _i; i++) { +// elems[elems.length] = <ResidueView ctx={ctx} seqId={offset + i} letter={sequence[i]} parent={this} key={i} />; +// } + +// return <div style={{ wordWrap: 'break-word' }}> +// <span style={{ fontWeight: 'bold' }}>{this.props.seq.entityId}:{offset} </span> +// {elems} +// </div>; +// } +// } + +// class ResidueView extends React.Component<{ ctx: Context, seqId: number, letter: string, parent: EntitySequence }, { isHighlighted: boolean }> { +// state = { isHighlighted: false } + +// mouseEnter = () => { +// this.setState({ isHighlighted: true }); +// this.props.parent.raiseInteractityEvent(this.props.seqId); +// } + +// mouseLeave = () => { +// this.setState({ isHighlighted: false }); +// this.props.parent.raiseInteractityEvent(); +// } + +// render() { +// return <span onMouseEnter={this.mouseEnter} onMouseLeave={this.mouseLeave} +// style={{ cursor: 'pointer', backgroundColor: this.state.isHighlighted ? 'yellow' : void 0 }}> +// {this.props.letter} +// </span>; +// } +// } \ No newline at end of file diff --git a/src/mol-app/context/context.ts b/src/mol-app/context/context.ts deleted file mode 100644 index 5c8fee555e120226afad3fc1ecf5e58c0ea95655..0000000000000000000000000000000000000000 --- a/src/mol-app/context/context.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { UUID } from 'mol-util' -import { PerformanceMonitor } from 'mol-util/performance-monitor'; -import { Dispatcher } from '../service/dispatcher' -import { Logger } from '../service/logger' -import { LayoutTarget, LayoutController } from '../controller/layout'; -import { ViewportController } from '../controller/visualization/viewport'; -import { Stage } from 'mol-view/stage'; -import { AnyTransform } from 'mol-view/state/transform'; -import { BehaviorSubject } from 'rxjs'; -import { AnyEntity } from 'mol-view/state/entity'; -import { SequenceViewController } from '../controller/visualization/sequence-view'; - -export class Settings { - private settings = new Map<string, any>(); - - set(key: string, value: any) { - this.settings.set(key, value); - } - - get(key: string) { - return this.settings.get(key); - } -} - -export class Context { - id = UUID.create() - - dispatcher = new Dispatcher(); - logger = new Logger(this); - performance = new PerformanceMonitor(); - - stage = new Stage(this); - viewport = new ViewportController(this); - layout: LayoutController; - settings = new Settings(); - - // TODO: this is a temporary solution - components = { - sequenceView: new SequenceViewController(this) - }; - - currentEntity = new BehaviorSubject(undefined) as BehaviorSubject<AnyEntity | undefined> - currentTransforms = new BehaviorSubject([] as AnyTransform[]) - - createLayout(targets: LayoutTarget[], target: HTMLElement) { - this.layout = new LayoutController(this, targets, target); - } - - initStage(canvas: HTMLCanvasElement, container: HTMLDivElement) { - this.stage.initRenderer(canvas, container) - return true - } - - destroy() { - if (this.stage) { - this.stage.dispose() - this.stage = null as any - } - } -} \ No newline at end of file diff --git a/src/mol-app/controller/controller.ts b/src/mol-app/controller/controller.ts deleted file mode 100644 index bfd6127f6dd7efbb395557f071be100bb4c3b68b..0000000000000000000000000000000000000000 --- a/src/mol-app/controller/controller.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { BehaviorSubject } from 'rxjs'; -import { merge } from 'mol-util'; -import { Context } from '../context/context' -import { LayoutRegion } from './layout'; - -export class Controller<State> { - - private _state = new BehaviorSubject<State>(<any>void 0); - private _latestState: State = <any>void 0; - - get dispatcher() { - return this.context.dispatcher; - } - - setState(...states: Partial<State>[]) { - let s = merge(this._latestState, ...states); - if (s !== this._latestState) { - this._latestState = s; - this._state.next(s); - } - } - - get state() { - return this._state; - } - - get latestState() { - return this._latestState; - } - - constructor(public context: Context, initialState: State) { - this._latestState = initialState; - } -} - -export interface ControllerInfo { - key: string; - controller: Controller<any>; - view: any; - region: LayoutRegion; - isStatic?: boolean; -} \ No newline at end of file diff --git a/src/mol-app/controller/entity/tree.ts b/src/mol-app/controller/entity/tree.ts deleted file mode 100644 index fdcb620e550079976e69b6595d58ac55c56ebe28..0000000000000000000000000000000000000000 --- a/src/mol-app/controller/entity/tree.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { Context } from '../../context/context' -import { Controller } from '../controller'; -import { AnyEntity } from 'mol-view/state/entity'; - -export interface EntityTreeState { - entities: Set<AnyEntity> -} - -export class EntityTreeController extends Controller<EntityTreeState> { - constructor(context: Context) { - super(context, { entities: new Set() }); - - context.stage.ctx.change.subscribe(() => { - if (context.stage.ctx) { - this.state.next({ entities: context.stage.ctx.entities }) // TODO - this.setState({ entities: context.stage.ctx.entities }) - } - }) - } -} \ No newline at end of file diff --git a/src/mol-app/controller/layout.ts b/src/mol-app/controller/layout.ts deleted file mode 100644 index 388f57788aecd7465ca1d66a40bae2032b2d120b..0000000000000000000000000000000000000000 --- a/src/mol-app/controller/layout.ts +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { Context } from '../context/context' -import { Controller, ControllerInfo } from './controller' -import { CommonEvents, LayoutEvents } from '../event/basic'; - -export enum LayoutRegion { - Main = 0, - Top = 1, - Right = 2, - Bottom = 3, - Left = 4, - Root = 5 -} - -export enum CollapsedControlsLayout { - Outside = 0, - Landscape = 1, - Portrait = 2 -} - -export class LayoutTarget { - components: ControllerInfo[] = []; - constructor(public cssClass: string) { - } -} - -export function makeEmptyTargets() { - let ret: LayoutTarget[] = []; - for (let i = 0; i <= LayoutRegion.Root; i++) { - ret.push(new LayoutTarget(LayoutRegion[i].toLowerCase())); - } - return ret; -} - -export type RegionState = 'Hidden' | 'Sticky' | 'Default' - -export interface LayoutState { - isExpanded: boolean, - hideControls: boolean, - collapsedControlsLayout: CollapsedControlsLayout, - regionStates?: { [region: number]: RegionState } -} - -interface RootState { - top: string | null, - bottom: string | null, - left: string | null, - right: string | null, - - width: string | null; - height: string | null; - maxWidth: string | null; - maxHeight: string | null; - margin: string | null; - marginLeft: string | null; - marginRight: string | null; - marginTop: string | null; - marginBottom: string | null; - - scrollTop: number, - scrollLeft: number, - position: string | null, - overflow: string | null, - viewports: HTMLElement[], - zindex: string | null -} - -export class LayoutController extends Controller<LayoutState> { - - update(state: Partial<LayoutState>) { - let prevExpanded = !!this.latestState.isExpanded; - this.setState(state); - if (typeof state.isExpanded === 'boolean' && state.isExpanded !== prevExpanded) this.handleExpand(); - - this.dispatcher.schedule(() => CommonEvents.LayoutChanged.dispatch(this.context, {})); - } - - private rootState: RootState | undefined = void 0; - private expandedViewport: HTMLMetaElement; - - private getScrollElement() { - if ((document as any).scrollingElement) return (document as any).scrollingElement; - if (document.documentElement) return document.documentElement; - return document.body; - } - - private handleExpand() { - try { - let body = document.getElementsByTagName('body')[0]; - let head = document.getElementsByTagName('head')[0]; - - if (!body || !head) return; - - if (this.latestState.isExpanded) { - - let children = head.children; - let hasExp = false; - let viewports: HTMLElement[] = []; - for (let i = 0; i < children.length; i++) { - if (children[i] === this.expandedViewport) { - hasExp = true; - } else if (((children[i] as any).name || '').toLowerCase() === 'viewport') { - viewports.push(children[i] as any); - } - } - - for (let v of viewports) { - head.removeChild(v); - } - - if (!hasExp) head.appendChild(this.expandedViewport); - - - let s = body.style; - - let doc = this.getScrollElement(); - let scrollLeft = doc.scrollLeft; - let scrollTop = doc.scrollTop; - - this.rootState = { - top: s.top, bottom: s.bottom, right: s.right, left: s.left, scrollTop, scrollLeft, position: s.position, overflow: s.overflow, viewports, zindex: this.root.style.zIndex, - width: s.width, height: s.height, - maxWidth: s.maxWidth, maxHeight: s.maxHeight, - margin: s.margin, marginLeft: s.marginLeft, marginRight: s.marginRight, marginTop: s.marginTop, marginBottom: s.marginBottom - }; - - s.overflow = 'hidden'; - s.position = 'fixed'; - s.top = '0'; - s.bottom = '0'; - s.right = '0'; - s.left = '0'; - - s.width = '100%'; - s.height = '100%'; - s.maxWidth = '100%'; - s.maxHeight = '100%'; - s.margin = '0'; - s.marginLeft = '0'; - s.marginRight = '0'; - s.marginTop = '0'; - s.marginBottom = '0'; - - this.root.style.zIndex = '100000'; - } else { - // root.style.overflow = rootOverflow; - let children = head.children; - for (let i = 0; i < children.length; i++) { - if (children[i] === this.expandedViewport) { - head.removeChild(this.expandedViewport); - break; - } - } - - if (this.rootState) { - let s = body.style, t = this.rootState; - for (let v of t.viewports) { - head.appendChild(v); - } - s.top = t.top; - s.bottom = t.bottom; - s.left = t.left; - s.right = t.right; - - s.width = t.width; - s.height = t.height; - s.maxWidth = t.maxWidth; - s.maxHeight = t.maxHeight; - s.margin = t.margin; - s.marginLeft = t.marginLeft; - s.marginRight = t.marginRight; - s.marginTop = t.marginTop; - s.marginBottom = t.marginBottom; - - s.position = t.position; - s.overflow = t.overflow; - let doc = this.getScrollElement(); - doc.scrollTop = t.scrollTop; - doc.scrollLeft = t.scrollLeft; - this.rootState = void 0; - this.root.style.zIndex = t.zindex; - } - } - } catch (e) { - this.context.logger.error('Layout change error, you might have to reload the page.'); - console.log('Layout change error, you might have to reload the page.', e); - } - } - - updateTargets(targets: LayoutTarget[]) { - this.targets = targets; - this.dispatcher.schedule(() => CommonEvents.ComponentsChanged.dispatch(this.context, {})); - } - - constructor(context: Context, public targets: LayoutTarget[], private root: HTMLElement) { - super(context, { - isExpanded: false, - hideControls: false, - collapsedControlsLayout: CollapsedControlsLayout.Outside, - regionStates: { } - }); - - LayoutEvents.SetState.getStream(this.context).subscribe(e => this.update(e.data)); - - // <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> - this.expandedViewport = document.createElement('meta') as any; - this.expandedViewport.name = 'viewport'; - this.expandedViewport.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'; - } -} \ No newline at end of file diff --git a/src/mol-app/controller/misc/jobs.ts b/src/mol-app/controller/misc/jobs.ts deleted file mode 100644 index 754edef44cc4b74910ea5da44affe5b395ad9c57..0000000000000000000000000000000000000000 --- a/src/mol-app/controller/misc/jobs.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import produce from 'immer' -import { filter } from 'rxjs/operators'; - -import { Controller } from '../controller' -import { JobEvents } from '../../event/basic'; -import { Context } from '../../context/context'; -import { Job } from '../../service/job'; - - -export interface JobInfo { - name: string; - message: string; - abort?: () => void -} - -export interface JobsState { - jobs: { [k: number]: JobInfo } -} - -export class JobsController extends Controller<JobsState> { - private updated(state: Job.State) { - let isWatched = state.type === this.type; - let jobs = this.latestState.jobs!; - - if (!isWatched) { - if (jobs[state.jobId] !== undefined) { - jobs = produce(jobs, _jobs => { delete _jobs[state.jobId] }); - this.setState({ jobs }); - } - return; - } - - jobs = produce(jobs, _jobs => { - _jobs[state.jobId] = { - name: state.name, - message: state.message, - abort: state.abort - }; - }) - this.setState({ jobs }); - } - - private started(job: Job.Info) { - this.setState({ - jobs: produce(this.latestState.jobs!, _jobs => { - _jobs[job.id] = { name: job.name, message: 'Running...' } - }) - }); - } - - private completed(taskId: number) { - if (!this.latestState.jobs![taskId]) return; - - this.setState({ - jobs: produce(this.latestState.jobs!, _jobs => { delete _jobs[taskId] }) - }); - } - - constructor(context: Context, private type: Job.Type) { - super(context, { - jobs: {} - }); - - JobEvents.StateUpdated.getStream(this.context) - .subscribe(e => this.updated(e.data)); - - JobEvents.Started.getStream(this.context).pipe( - filter(e => e.data.type === type)) - .subscribe(e => this.started(e.data)); - - JobEvents.Completed.getStream(this.context) - .subscribe(e => this.completed(e.data)); - } -} \ No newline at end of file diff --git a/src/mol-app/controller/misc/log.ts b/src/mol-app/controller/misc/log.ts deleted file mode 100644 index d703375a8c5514941b354bce86c3222739cd376a..0000000000000000000000000000000000000000 --- a/src/mol-app/controller/misc/log.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import produce from 'immer' - -import { Controller } from '../controller' -import { Context } from '../../context/context'; -import { LogEvent } from '../../event/basic'; -import { Logger } from '../../service/logger'; - -export class LogController extends Controller<{ entries: Logger.Entry[] }> { - constructor(context: Context) { - super(context, { entries: [] }); - - LogEvent.getStream(this.context) - .subscribe(e => this.setState({ - entries: produce(this.latestState.entries, _entries => { _entries.push(e.data) }) - })) - } -} \ No newline at end of file diff --git a/src/mol-app/controller/transform/list.ts b/src/mol-app/controller/transform/list.ts deleted file mode 100644 index 75ee2b5c23d3b0553e87af5582cb9079bfee2484..0000000000000000000000000000000000000000 --- a/src/mol-app/controller/transform/list.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { Context } from '../../context/context' -import { Controller } from '../controller'; -import { AnyTransform } from 'mol-view/state/transform'; -import { AnyEntity } from 'mol-view/state/entity'; - -export interface TransformListState { - entity?: AnyEntity - transforms: AnyTransform[] -} - -export class TransformListController extends Controller<TransformListState> { - constructor(context: Context) { - super(context, { transforms: [], entity: undefined }); - - context.currentTransforms.subscribe((transforms) => { - this.state.next({ transforms, entity: context.currentEntity.getValue() }) // TODO - this.setState({ transforms, entity: context.currentEntity.getValue() }) - }) - } -} \ No newline at end of file diff --git a/src/mol-app/controller/visualization/sequence-view.ts b/src/mol-app/controller/visualization/sequence-view.ts deleted file mode 100644 index 17423f9806beef2b22a3eb3c4a4117eed3bf1534..0000000000000000000000000000000000000000 --- a/src/mol-app/controller/visualization/sequence-view.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author David Sehnal <david.sehnal@gmail.com> - */ - -import { shallowClone } from 'mol-util'; -import { Context } from '../../context/context' -import { Controller } from '../controller'; -import { Structure } from 'mol-model/structure'; - -export const DefaultSequenceViewState = { - structure: void 0 as (Structure | undefined) -} -export type SequenceViewState = typeof DefaultSequenceViewState - -export class SequenceViewController extends Controller<SequenceViewState> { - constructor(context: Context) { - super(context, shallowClone(DefaultSequenceViewState)); - } -} \ No newline at end of file diff --git a/src/mol-app/controller/visualization/viewport.ts b/src/mol-app/controller/visualization/viewport.ts deleted file mode 100644 index 40a4ac53a3726f7cdf4a22a6867ab4b1fd6d8404..0000000000000000000000000000000000000000 --- a/src/mol-app/controller/visualization/viewport.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -// import { throttle } from 'rxjs/operators'; -// import { interval } from 'rxjs'; - -import { shallowClone } from 'mol-util'; -import { Context } from '../../context/context' -import { Controller } from '../controller'; - -export const DefaultViewportOptions = { - clearColor: { r: 1, g: 1, b: 1 }, - enableFog: true, - cameraFOV: 30, - cameraSpeed: 4 -} -export type ViewportOptions = typeof DefaultViewportOptions - -export class ViewportController extends Controller<ViewportOptions> { - constructor(context: Context) { - super(context, shallowClone(DefaultViewportOptions)); - } -} \ No newline at end of file diff --git a/src/mol-app/event/basic.ts b/src/mol-app/event/basic.ts deleted file mode 100644 index f52d6e651296d7839c83388cfa827587949aa553..0000000000000000000000000000000000000000 --- a/src/mol-app/event/basic.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { Event } from './event' -import { Logger } from '../service/logger'; -import { Dispatcher } from '../service/dispatcher' -import { LayoutState } from '../controller/layout'; -import { ViewportOptions } from '../controller/visualization/viewport'; -import { Job } from '../service/job'; -import { Loci } from 'mol-model/loci'; - -const Lane = Dispatcher.Lane; - -export const LogEvent = Event.create<Logger.Entry>('bs.Log', Lane.Log); - -export namespace CommonEvents { - export const LayoutChanged = Event.create('bs.Common.LayoutChanged', Lane.Slow); - export const ComponentsChanged = Event.create('bs.Common.ComponentsChanged', Lane.Slow); -} - -export namespace JobEvents { - export const Started = Event.create<Job.Info>('bs.Jobs.Started', Lane.Job); - export const Completed = Event.create<number>('bs.Jobs.Completed', Lane.Job); - export const StateUpdated = Event.create<Job.State>('bs.Jobs.StateUpdated', Lane.Busy); -} - -export namespace LayoutEvents { - export const SetState = Event.create<Partial<LayoutState>>('lm.cmd.Layout.SetState', Lane.Slow); - export const SetViewportOptions = Event.create<ViewportOptions>('bs.cmd.Layout.SetViewportOptions', Lane.Slow); -} - -export namespace InteractivityEvents { - export const HighlightLoci = Event.create<Loci>('bs.Interactivity.HighlightLoci', Lane.Slow); - export const SelectLoci = Event.create<Loci>('bs.Interactivity.SelectLoci', Lane.Slow); - export const LabelLoci = Event.create<Loci>('bs.Interactivity.LabelLoci', Lane.Slow); -} diff --git a/src/mol-app/event/event.ts b/src/mol-app/event/event.ts deleted file mode 100644 index 4e6affecc6620074f229179e54ee8c12624846f6..0000000000000000000000000000000000000000 --- a/src/mol-app/event/event.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { Observable } from 'rxjs'; -import { Context } from '../context/context' -import { Dispatcher } from '../service/dispatcher' - -export interface Event<T> { - type: Event.Type<T>; - data: T; -} - -export namespace Event { - export type Stream<T> = Observable<Event<T>>; - - import Lane = Dispatcher.Lane - - export type Any = Event<any> - export type AnyType = Type<any> - - export interface Type<T> { - name: string, - lane: Lane, - dispatch(context: Context, data: T): void; - getStream(context: Context): Stream<T>; - } - - const EventPrototype = { - dispatch<T>(this: any, context: Context, data: T) { context.dispatcher.dispatch({ type: this, data }) }, - getStream(this: any, context: Context) { return context.dispatcher.getStream(this); } - } - - export function create<T>(name: string, lane: Dispatcher.Lane): Type<T> { - return Object.create(EventPrototype, { - name: { writable: false, configurable: false, value: name }, - lane: { writable: false, configurable: false, value: lane } - }); - } -} \ No newline at end of file diff --git a/src/mol-app/service/dispatcher.ts b/src/mol-app/service/dispatcher.ts deleted file mode 100644 index 58a6345c601a7dfc16cbc6d162c814235efdda2f..0000000000000000000000000000000000000000 --- a/src/mol-app/service/dispatcher.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { Subject } from 'rxjs'; -import { filter } from 'rxjs/operators'; -import { Event } from '../event/event' - -export class Dispatcher { - LOG_DISPATCH_STREAM = false; - - private lanes: Subject<Event<any>>[] = []; - constructor() { - for (let i = 0; i <= Dispatcher.Lane.Job; i++) { - this.lanes.push(new Subject<Event<any>>()); - } - } - - dispatch<T>(event: Event<T>) { - if (this.LOG_DISPATCH_STREAM) console.log(event.type.name, Dispatcher.Lane[event.type.lane], event.data); - this.lanes[event.type.lane].next(event); - } - - schedule(action: () => void, onError?: (e: string) => void, timeout = 1000 / 31) { - return setTimeout(() => { - if (onError) { - try { - action.call(null) - } catch (e) { - onError.call(null, '' + e); - } - } else { - action.call(null); - } - }, timeout); - } - - getStream<T>(type: Event.Type<T>): Event.Stream<T> { - return this.lanes[type.lane].pipe(filter(e => e.type === type)); - } - - finished() { - this.lanes.forEach(l => l.complete()); - } -} - -export namespace Dispatcher { - export enum Lane { - Slow = 0, - Fast = 1, - Log = 2, - Busy = 3, - Transformer = 4, - Job = 5 - } -} \ No newline at end of file diff --git a/src/mol-app/service/job.ts b/src/mol-app/service/job.ts deleted file mode 100644 index 3bfd0263ef88655bd885c945267c182efce00183..0000000000000000000000000000000000000000 --- a/src/mol-app/service/job.ts +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { Context } from '../context/context' -import { JobEvents } from '../event/basic'; -import { PerformanceMonitor } from 'mol-util/performance-monitor'; -import { formatProgress } from 'mol-util'; -import { Progress, Task } from 'mol-task'; - -export class Job<T> { - private info: Job.Info; - get id() { return this.info.id; } - get reportTime() { return this.info.reportTime; } - - run(context: Context) { - return this.runWithContext(context).result; - } - - runWithContext(context: Context): Job.Running<T> { - return new Job.Running(context, this.task, this.info); - } - - setReportTime(report: boolean) { - this.info.reportTime = report; - return this; - } - - constructor(public name: string, public type: Job.Type, private task: Task<T>) { - this.info = { - id: serialJobId++, - name, - type, - reportTime: false - }; - } -} - -let serialJobId = 0; -export namespace Job { - export let __DEBUG_MODE__ = false; - - export type Type = 'Normal' | 'Background' | 'Silent'; - - export interface Info { - id: number, - type: Type, - name: string, - reportTime: boolean - } - - export class Running<T> { - result: Promise<T>; - - private progressUpdated(progress: Progress) { - JobEvents.StateUpdated.dispatch(this.context, { - jobId: this.info.id, - type: this.info.type, - name: this.info.name, - message: formatProgress(progress), - abort: progress.requestAbort - }); - } - - private resolved() { - try { - this.context.performance.end('job' + this.info.id); - if (this.info.reportTime) { - let time = this.context.performance.time('job' + this.info.id); - if (this.info.type !== 'Silent') this.context.logger.info(`${this.info.name} finished in ${PerformanceMonitor.format(time)}.`) - } - } finally { - JobEvents.Completed.dispatch(this.context, this.info.id); - } - } - - private rejected(err: any) { - this.context.performance.end('job' + this.info.id); - this.context.performance.formatTime('job' + this.info.id); - - if (__DEBUG_MODE__) { - console.error(err); - } - - try { - if (this.info.type === 'Silent') { - if (err.warn) this.context.logger.warning(`Warning (${this.info.name}): ${err.message}`); - else console.error(`Error (${this.info.name})`, err); - } else { - if (err.warn) { - this.context.logger.warning(`Warning (${this.info.name}): ${err.message}`); - } else { - let e = '' + err; - if (e.indexOf('Aborted') >= 0) this.context.logger.info(`${this.info.name}: Aborted.`); - else this.context.logger.error(`Error (${this.info.name}): ${err}`); - } - } - } catch (e) { - console.error(e); - } finally { - JobEvents.Completed.dispatch(this.context, this.info.id); - } - } - - private run() { - JobEvents.Started.dispatch(this.context, this.info); - this.context.performance.start('job' + this.info.id); - - this.result = this.task.run((p: Progress) => this.progressUpdated(p), 250) - this.result.then(() => this.resolved()).catch(e => this.rejected(e)); - } - - constructor(private context: Context, private task: Task<T>, private info: Info) { - this.run(); - } - } - - export interface State { - jobId: number, - type: Type, - name: string, - message: string, - abort?: () => void - } - - export function create<T>(name: string, type: Type, task: Task<T>) { - return new Job<T>(name, type, task); - } -} \ No newline at end of file diff --git a/src/mol-app/service/logger.ts b/src/mol-app/service/logger.ts deleted file mode 100644 index 901596719a035024e00f5a3c117ba4dc4e135ed2..0000000000000000000000000000000000000000 --- a/src/mol-app/service/logger.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import { LogEvent } from '../event/basic' -import { Context } from '../context/context' - -export class Logger { - - private log(e: Logger.Entry) { - LogEvent.dispatch(this.context, e); - } - - message(m: string) { - this.log({ type: Logger.EntryType.Message, timestamp: new Date(), message: m }); - } - - error(m: string) { - this.log({ type: Logger.EntryType.Error, timestamp: new Date(), message: m }); - } - - warning(m: string) { - this.log({ type: Logger.EntryType.Warning, timestamp: new Date(), message: m }); - } - - info(m: string) { - this.log({ type: Logger.EntryType.Info, timestamp: new Date(), message: m }); - } - - constructor(private context: Context) { - - } -} - -export namespace Logger { - export enum EntryType { - Message, - Error, - Warning, - Info - } - - export interface Entry { - type: EntryType; - timestamp: Date; - message: any - } -} \ No newline at end of file diff --git a/src/mol-app/skin/base.scss b/src/mol-app/skin/base.scss deleted file mode 100644 index 355f0eccabe5e385cf87fb59e1d0b23c6bfe72fb..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/base.scss +++ /dev/null @@ -1,45 +0,0 @@ - -@font-face { - font-family: 'fontello'; - src: url('./fonts/fontello.eot'); - src: url('./fonts/fontello.eot#iefix') format('embedded-opentype'), - url('./fonts/fontello.woff2') format('woff2'), - url('./fonts/fontello.woff') format('woff'), - url('./fonts/fontello.ttf') format('truetype'), - url('./fonts/fontello.svg#fontello') format('svg'); - font-weight: normal; - font-style: normal; -} - -@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,700); - -.molstar-plugin { - font-family: "Helvetica Neue", "Source Sans Pro", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - @import 'variables'; - - // for bootstrap - $border-radius-base: 0; - $border-radius-large: 0; - $border-radius-small: 0; - - @import 'bootstrap'; - - @import 'icons'; - @import 'layout'; - @import 'ui'; - @import 'logo'; - - .molstar-plugin-content { - color: $font-color; - } - - background: $default-background; -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap.scss b/src/mol-app/skin/bootstrap.scss deleted file mode 100644 index f26fdba911a808e6de47e05e6226d84f956a84d8..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap.scss +++ /dev/null @@ -1,25 +0,0 @@ -/*! - * Bootstrap v3.3.6 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -// Core variables and mixins -@import "bootstrap/variables"; -@import "bootstrap/mixins"; - -// Reset and dependencies -@import "bootstrap/normalize"; - -// Core CSS -@import "bootstrap/scaffolding"; -@import "bootstrap/type"; -@import "bootstrap/forms"; -@import "bootstrap/buttons"; - -// Components -@import "bootstrap/button-groups"; -@import "bootstrap/input-groups"; - -@import "bootstrap/labels"; -@import "bootstrap/badges"; diff --git a/src/mol-app/skin/bootstrap/badges.scss b/src/mol-app/skin/bootstrap/badges.scss deleted file mode 100644 index b03cc5562b6aa3a752dea7960206ad146facd24f..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/badges.scss +++ /dev/null @@ -1,68 +0,0 @@ -// -// Badges -// -------------------------------------------------- - - -// Base class -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: $font-size-small; - font-weight: $badge-font-weight; - color: $badge-color; - line-height: $badge-line-height; - vertical-align: middle; - white-space: nowrap; - text-align: center; - background-color: $badge-bg; - border-radius: $badge-border-radius; - - // Empty badges collapse automatically (not available in IE8) - &:empty { - display: none; - } - - // Quick fix for badges in buttons - .molstar-btn & { - position: relative; - top: -1px; - } - - .molstar-btn-xs &, - .molstar-btn-group-xs > .molstar-btn & { - top: 0; - padding: 1px 5px; - } - - // [converter] extracted a& to a.badge - - // Account for badges in navs - .list-group-item.active > &, - .nav-pills > .active > a > & { - color: $badge-active-color; - background-color: $badge-active-bg; - } - - .list-group-item > & { - float: right; - } - - .list-group-item > & + & { - margin-right: 5px; - } - - .nav-pills > li > a > & { - margin-left: 3px; - } - } - - // Hover state, but only for links - a.badge { - &:hover, - &:focus { - color: $badge-link-hover-color; - text-decoration: none; - cursor: pointer; - } - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/button-groups.scss b/src/mol-app/skin/bootstrap/button-groups.scss deleted file mode 100644 index 3fd6d085e2760ba38823f4a32c1de9aaf8e0894f..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/button-groups.scss +++ /dev/null @@ -1,244 +0,0 @@ -// -// Button groups -// -------------------------------------------------- - -// Make the div behave like a button -.molstar-btn-group, -.molstar-btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; // match .molstar-btn alignment given font-size hack above - > .molstar-btn { - position: relative; - float: left; - // Bring the "active" button to the front - &:hover, - &:focus, - &:active, - &.active { - z-index: 2; - } - } -} - -// Prevent double borders when buttons are next to each other -.molstar-btn-group { - .molstar-btn + .molstar-btn, - .molstar-btn + .molstar-btn-group, - .molstar-btn-group + .molstar-btn, - .molstar-btn-group + .molstar-btn-group { - margin-left: -1px; - } -} - -// Optional: Group multiple button groups together for a toolbar -.molstar-btn-toolbar { - margin-left: -5px; // Offset the first child's margin - @include clearfix; - - .molstar-btn, - .molstar-btn-group, - .input-group { - float: left; - } - > .molstar-btn, - > .molstar-btn-group, - > .input-group { - margin-left: 5px; - } -} - -.molstar-btn-group > .molstar-btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} - -// Set corners individual because sometimes a single button can be in a .molstar-btn-group and we need :first-child and :last-child to both match -.molstar-btn-group > .molstar-btn:first-child { - margin-left: 0; - &:not(:last-child):not(.dropdown-toggle) { - @include border-right-radius(0); - } -} -// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it -.molstar-btn-group > .molstar-btn:last-child:not(:first-child), -.molstar-btn-group > .dropdown-toggle:not(:first-child) { - @include border-left-radius(0); -} - -// Custom edits for including molstar-btn-groups within molstar-btn-groups (useful for including dropdown buttons within a molstar-btn-group) -.molstar-btn-group > .molstar-btn-group { - float: left; -} -.molstar-btn-group > .molstar-btn-group:not(:first-child):not(:last-child) > .molstar-btn { - border-radius: 0; -} -.molstar-btn-group > .molstar-btn-group:first-child:not(:last-child) { - > .molstar-btn:last-child, - > .dropdown-toggle { - @include border-right-radius(0); - } -} -.molstar-btn-group > .molstar-btn-group:last-child:not(:first-child) > .molstar-btn:first-child { - @include border-left-radius(0); -} - -// On active and open, don't show outline -.molstar-btn-group .dropdown-toggle:active, -.molstar-btn-group.open .dropdown-toggle { - outline: 0; -} - - -// Sizing -// -// Remix the default button sizing classes into new ones for easier manipulation. - -.molstar-btn-group-xs > .molstar-btn { @extend .molstar-btn-xs; } -.molstar-btn-group-sm > .molstar-btn { @extend .molstar-btn-sm; } -.molstar-btn-group-lg > .molstar-btn { @extend .molstar-btn-lg; } - - -// Split button dropdowns -// ---------------------- - -// Give the line between buttons some depth -.molstar-btn-group > .molstar-btn + .dropdown-toggle { - padding-left: 8px; - padding-right: 8px; -} -.molstar-btn-group > .molstar-btn-lg + .dropdown-toggle { - padding-left: 12px; - padding-right: 12px; -} - -// The clickable button for toggling the menu -// Remove the gradient and set the same inset shadow as the :active state -.molstar-btn-group.open .dropdown-toggle { - @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); - - // Show no shadow for `.molstar-btn-link` since it has no other button styles. - &.molstar-btn-link { - @include box-shadow(none); - } -} - - -// Reposition the caret -.molstar-btn .caret { - margin-left: 0; -} -// Carets in other button sizes -.molstar-btn-lg .caret { - border-width: $caret-width-large $caret-width-large 0; - border-bottom-width: 0; -} -// Upside down carets for .dropup -.dropup .molstar-btn-lg .caret { - border-width: 0 $caret-width-large $caret-width-large; -} - - -// Vertical button groups -// ---------------------- - -.molstar-btn-group-vertical { - > .molstar-btn, - > .molstar-btn-group, - > .molstar-btn-group > .molstar-btn { - display: block; - float: none; - width: 100%; - max-width: 100%; - } - - // Clear floats so dropdown menus can be properly placed - > .molstar-btn-group { - @include clearfix; - > .molstar-btn { - float: none; - } - } - - > .molstar-btn + .molstar-btn, - > .molstar-btn + .molstar-btn-group, - > .molstar-btn-group + .molstar-btn, - > .molstar-btn-group + .molstar-btn-group { - margin-top: -1px; - margin-left: 0; - } -} - -.molstar-btn-group-vertical > .molstar-btn { - &:not(:first-child):not(:last-child) { - border-radius: 0; - } - &:first-child:not(:last-child) { - @include border-top-radius($molstar-btn-border-radius-base); - @include border-bottom-radius(0); - } - &:last-child:not(:first-child) { - @include border-top-radius(0); - @include border-bottom-radius($molstar-btn-border-radius-base); - } -} -.molstar-btn-group-vertical > .molstar-btn-group:not(:first-child):not(:last-child) > .molstar-btn { - border-radius: 0; -} -.molstar-btn-group-vertical > .molstar-btn-group:first-child:not(:last-child) { - > .molstar-btn:last-child, - > .dropdown-toggle { - @include border-bottom-radius(0); - } -} -.molstar-btn-group-vertical > .molstar-btn-group:last-child:not(:first-child) > .molstar-btn:first-child { - @include border-top-radius(0); -} - - -// Justified button groups -// ---------------------- - -.molstar-btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; - > .molstar-btn, - > .molstar-btn-group { - float: none; - display: table-cell; - width: 1%; - } - > .molstar-btn-group .molstar-btn { - width: 100%; - } - - > .molstar-btn-group .dropdown-menu { - left: auto; - } -} - - -// Checkbox and radio options -// -// In order to support the browser's form validation feedback, powered by the -// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use -// `display: none;` or `visibility: hidden;` as that also hides the popover. -// Simply visually hiding the inputs via `opacity` would leave them clickable in -// certain cases which is prevented by using `clip` and `pointer-events`. -// This way, we ensure a DOM element is visible to position the popover from. -// -// See https://github.com/twbs/bootstrap/pull/12794 and -// https://github.com/twbs/bootstrap/pull/14559 for more information. - -[data-toggle="buttons"] { - > .molstar-btn, - > .molstar-btn-group > .molstar-btn { - input[type="radio"], - input[type="checkbox"] { - position: absolute; - clip: rect(0,0,0,0); - pointer-events: none; - } - } -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/buttons.scss b/src/mol-app/skin/bootstrap/buttons.scss deleted file mode 100644 index f775ee279506b373097a9aa27beb2a91c3d6950c..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/buttons.scss +++ /dev/null @@ -1,168 +0,0 @@ -// -// Buttons -// -------------------------------------------------- - - -// Base styles -// -------------------------------------------------- - -.molstar-btn { - display: inline-block; - margin-bottom: 0; // For input.molstar-btn - font-weight: $molstar-btn-font-weight; - text-align: center; - vertical-align: middle; - touch-action: manipulation; - cursor: pointer; - background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid transparent; - white-space: nowrap; - @include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $molstar-btn-border-radius-base); - @include user-select(none); - - &, - &:active, - &.active { - &:focus, - &.focus { - @include tab-focus; - } - } - - &:hover, - &:focus, - &.focus { - color: $molstar-btn-default-color; - text-decoration: none; - } - - &:active, - &.active { - outline: 0; - background-image: none; - @include box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); - } - - &.disabled, - &[disabled], - fieldset[disabled] & { - cursor: $cursor-disabled; - @include opacity(.65); - @include box-shadow(none); - } - - // [converter] extracted a& to a.molstar-btn - } - - a.molstar-btn { - &.disabled, - fieldset[disabled] & { - pointer-events: none; // Future-proof disabling of clicks on `<a>` elements - } - } - - - // Alternate buttons - // -------------------------------------------------- - - .molstar-btn-default { - @include button-variant($molstar-btn-default-color, $molstar-btn-default-bg, $molstar-btn-default-border); - } - .molstar-btn-primary { - @include button-variant($molstar-btn-primary-color, $molstar-btn-primary-bg, $molstar-btn-primary-border); - } - // Success appears as green - .molstar-btn-success { - @include button-variant($molstar-btn-success-color, $molstar-btn-success-bg, $molstar-btn-success-border); - } - // Info appears as blue-green - .molstar-btn-info { - @include button-variant($molstar-btn-info-color, $molstar-btn-info-bg, $molstar-btn-info-border); - } - // Warning appears as orange - .molstar-btn-warning { - @include button-variant($molstar-btn-warning-color, $molstar-btn-warning-bg, $molstar-btn-warning-border); - } - // Danger and error appear as red - .molstar-btn-danger { - @include button-variant($molstar-btn-danger-color, $molstar-btn-danger-bg, $molstar-btn-danger-border); - } - - - // Link buttons - // ------------------------- - - // Make a button look and behave like a link - .molstar-btn-link { - color: $link-color; - font-weight: normal; - border-radius: 0; - - &, - &:active, - &.active, - &[disabled], - fieldset[disabled] & { - background-color: transparent; - @include box-shadow(none); - } - &, - &:hover, - &:focus, - &:active { - border-color: transparent; - } - &:hover, - &:focus { - color: $link-hover-color; - text-decoration: $link-hover-decoration; - background-color: transparent; - } - &[disabled], - fieldset[disabled] & { - &:hover, - &:focus { - color: $molstar-btn-link-disabled-color; - text-decoration: none; - } - } - } - - - // Button Sizes - // -------------------------------------------------- - - .molstar-btn-lg { - // line-height: ensure even-numbered height of button next to large input - @include button-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $molstar-btn-border-radius-large); - } - .molstar-btn-sm { - // line-height: ensure proper height of button next to small input - @include button-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $molstar-btn-border-radius-small); - } - .molstar-btn-xs { - @include button-size($padding-xs-vertical, $padding-xs-horizontal, $font-size-small, $line-height-small, $molstar-btn-border-radius-small); - } - - - // Block button - // -------------------------------------------------- - - .molstar-btn-block { - display: block; - width: 100%; - } - - // Vertically space out multiple block buttons - .molstar-btn-block + .molstar-btn-block { - margin-top: 5px; - } - - // Specificity overrides - input[type="submit"], - input[type="reset"], - input[type="button"] { - &.molstar-btn-block { - width: 100%; - } - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/forms.scss b/src/mol-app/skin/bootstrap/forms.scss deleted file mode 100644 index b51eb372bc104ddf1fc19d35a212012308634fbc..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/forms.scss +++ /dev/null @@ -1,617 +0,0 @@ -// -// Forms -// -------------------------------------------------- - - -// Normalize non-controls -// -// Restyle and baseline non-control form elements. - -fieldset { - padding: 0; - margin: 0; - border: 0; - // Chrome and Firefox set a `min-width: min-content;` on fieldsets, - // so we reset that to ensure it behaves more like a standard block element. - // See https://github.com/twbs/bootstrap/issues/12359. - min-width: 0; - } - - legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: $line-height-computed; - font-size: ($font-size-base * 1.5); - line-height: inherit; - color: $legend-color; - border: 0; - border-bottom: 1px solid $legend-border-color; - } - - label { - display: inline-block; - max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141) - margin-bottom: 5px; - font-weight: bold; - } - - - // Normalize form controls - // - // While most of our form styles require extra classes, some basic normalization - // is required to ensure optimum display with or without those classes to better - // address browser inconsistencies. - - // Override content-box in Normalize (* isn't specific enough) - input[type="search"] { - @include box-sizing(border-box); - } - - // Position radios and checkboxes better - input[type="radio"], - input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; // IE8-9 - line-height: normal; - } - - input[type="file"] { - display: block; - } - - // Make range inputs behave like textual form controls - input[type="range"] { - display: block; - width: 100%; - } - - // Make multiple select elements height not fixed - select[multiple], - select[size] { - height: auto; - } - - // Focus for file, radio, and checkbox - input[type="file"]:focus, - input[type="radio"]:focus, - input[type="checkbox"]:focus { - @include tab-focus; - } - - // Adjust output element - output { - display: block; - padding-top: ($padding-base-vertical + 1); - font-size: $font-size-base; - line-height: $line-height-base; - color: $input-color; - } - - - // Common form controls - // - // Shared size and type resets for form controls. Apply `.molstar-form-control` to any - // of the following form controls: - // - // select - // textarea - // input[type="text"] - // input[type="password"] - // input[type="datetime"] - // input[type="datetime-local"] - // input[type="date"] - // input[type="month"] - // input[type="time"] - // input[type="week"] - // input[type="number"] - // input[type="email"] - // input[type="url"] - // input[type="search"] - // input[type="tel"] - // input[type="color"] - - .molstar-form-control { - display: block; - width: 100%; - height: $input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border) - padding: $padding-base-vertical $padding-base-horizontal; - font-size: $font-size-base; - line-height: $line-height-base; - color: $input-color; - background-color: $input-bg; - background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 - border: 1px solid $input-border; - border-radius: $input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS. - //@include box-shadow(none);//inset 0 1px 1px rgba(0,0,0,.075)); - //@include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s); - - // Customize the `:focus` state to imitate native WebKit styles. - @include molstar-form-control-focus; - - // Placeholder - @include placeholder; - - // Unstyle the caret on `<select>`s in IE10+. - &::-ms-expand { - border: 0; - background-color: transparent; - } - - // Disabled and read-only inputs - // - // HTML5 says that controls under a fieldset > legend:first-child won't be - // disabled if the fieldset is disabled. Due to implementation difficulty, we - // don't honor that edge case; we style them as disabled anyway. - &[disabled], - &[readonly], - fieldset[disabled] & { - background-color: $input-bg-disabled; - opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655 - } - - &[disabled], - fieldset[disabled] & { - cursor: $cursor-disabled; - } - - // [converter] extracted textarea& to textarea.molstar-form-control - } - - // Reset height for `textarea`s - textarea.molstar-form-control { - height: auto; - } - - - // Search inputs in iOS - // - // This overrides the extra rounded corners on search inputs in iOS so that our - // `.molstar-form-control` class can properly style them. Note that this cannot simply - // be added to `.molstar-form-control` as it's not specific enough. For details, see - // https://github.com/twbs/bootstrap/issues/11586. - - input[type="search"] { - -webkit-appearance: none; - } - - - // Special styles for iOS temporal inputs - // - // In Mobile Safari, setting `display: block` on temporal inputs causes the - // text within the input to become vertically misaligned. As a workaround, we - // set a pixel line-height that matches the given height of the input, but only - // for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848 - // - // Note that as of 8.3, iOS doesn't support `datetime` or `week`. - - @media screen and (-webkit-min-device-pixel-ratio: 0) { - input[type="date"], - input[type="time"], - input[type="datetime-local"], - input[type="month"] { - &.molstar-form-control { - line-height: $input-height-base; - } - - &.input-sm, - .input-group-sm & { - line-height: $input-height-small; - } - - &.input-lg, - .input-group-lg & { - line-height: $input-height-large; - } - } - } - - - // Form groups - // - // Designed to help with the organization and spacing of vertical forms. For - // horizontal forms, use the predefined grid classes. - - .form-group { - margin-bottom: $form-group-margin-bottom; - } - - - // Checkboxes and radios - // - // Indent the labels to position radios/checkboxes as hanging controls. - - .radio, - .checkbox { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px; - - label { - min-height: $line-height-computed; // Ensure the input doesn't jump when there is no text - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; - } - } - .radio input[type="radio"], - .radio-inline input[type="radio"], - .checkbox input[type="checkbox"], - .checkbox-inline input[type="checkbox"] { - position: absolute; - margin-left: -20px; - margin-top: 4px \9; - } - - .radio + .radio, - .checkbox + .checkbox { - margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing - } - - // Radios and checkboxes on same line - .radio-inline, - .checkbox-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - vertical-align: middle; - font-weight: normal; - cursor: pointer; - } - .radio-inline + .radio-inline, - .checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; // space out consecutive inline controls - } - - // Apply same disabled cursor tweak as for inputs - // Some special care is needed because <label>s don't inherit their parent's `cursor`. - // - // Note: Neither radios nor checkboxes can be readonly. - input[type="radio"], - input[type="checkbox"] { - &[disabled], - &.disabled, - fieldset[disabled] & { - cursor: $cursor-disabled; - } - } - // These classes are used directly on <label>s - .radio-inline, - .checkbox-inline { - &.disabled, - fieldset[disabled] & { - cursor: $cursor-disabled; - } - } - // These classes are used on elements with <label> descendants - .radio, - .checkbox { - &.disabled, - fieldset[disabled] & { - label { - cursor: $cursor-disabled; - } - } - } - - - // Static form control text - // - // Apply class to a `p` element to make any string of text align with labels in - // a horizontal form layout. - - .molstar-form-control-static { - // Size it appropriately next to real form controls - padding-top: ($padding-base-vertical + 1); - padding-bottom: ($padding-base-vertical + 1); - // Remove default margin from `p` - margin-bottom: 0; - min-height: ($line-height-computed + $font-size-base); - - &.input-lg, - &.input-sm { - padding-left: 0; - padding-right: 0; - } - } - - - // Form control sizing - // - // Build on `.molstar-form-control` with modifier classes to decrease or increase the - // height and font-size of form controls. - // - // The `.form-group-* molstar-form-control` variations are sadly duplicated to avoid the - // issue documented in https://github.com/twbs/bootstrap/issues/15074. - - @include input-size('.input-sm', $input-height-small, $padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $input-border-radius-small); - .form-group-sm { - .molstar-form-control { - height: $input-height-small; - padding: $padding-small-vertical $padding-small-horizontal; - font-size: $font-size-small; - line-height: $line-height-small; - border-radius: $input-border-radius-small; - } - select.molstar-form-control { - height: $input-height-small; - line-height: $input-height-small; - } - textarea.molstar-form-control, - select[multiple].molstar-form-control { - height: auto; - } - .molstar-form-control-static { - height: $input-height-small; - min-height: ($line-height-computed + $font-size-small); - padding: ($padding-small-vertical + 1) $padding-small-horizontal; - font-size: $font-size-small; - line-height: $line-height-small; - } - } - - @include input-size('.input-lg', $input-height-large, $padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $input-border-radius-large); - .form-group-lg { - .molstar-form-control { - height: $input-height-large; - padding: $padding-large-vertical $padding-large-horizontal; - font-size: $font-size-large; - line-height: $line-height-large; - border-radius: $input-border-radius-large; - } - select.molstar-form-control { - height: $input-height-large; - line-height: $input-height-large; - } - textarea.molstar-form-control, - select[multiple].molstar-form-control { - height: auto; - } - .molstar-form-control-static { - height: $input-height-large; - min-height: ($line-height-computed + $font-size-large); - padding: ($padding-large-vertical + 1) $padding-large-horizontal; - font-size: $font-size-large; - line-height: $line-height-large; - } - } - - - // Form control feedback states - // - // Apply contextual and semantic states to individual form controls. - - .has-feedback { - // Enable absolute positioning - position: relative; - - // Ensure icons don't overlap text - .molstar-form-control { - padding-right: ($input-height-base * 1.25); - } - } - // Feedback icon (requires .glyphicon classes) - .molstar-form-control-feedback { - position: absolute; - top: 0; - right: 0; - z-index: 2; // Ensure icon is above input groups - display: block; - width: $input-height-base; - height: $input-height-base; - line-height: $input-height-base; - text-align: center; - pointer-events: none; - } - .input-lg + .molstar-form-control-feedback, - .input-group-lg + .molstar-form-control-feedback, - .form-group-lg .molstar-form-control + .molstar-form-control-feedback { - width: $input-height-large; - height: $input-height-large; - line-height: $input-height-large; - } - .input-sm + .molstar-form-control-feedback, - .input-group-sm + .molstar-form-control-feedback, - .form-group-sm .molstar-form-control + .molstar-form-control-feedback { - width: $input-height-small; - height: $input-height-small; - line-height: $input-height-small; - } - - // Feedback states - .has-success { - @include molstar-form-control-validation($state-success-text, $state-success-text, $state-success-bg); - } - .has-warning { - @include molstar-form-control-validation($state-warning-text, $state-warning-text, $state-warning-bg); - } - .has-error { - @include molstar-form-control-validation($state-danger-text, $state-danger-text, $state-danger-bg); - } - - // Reposition feedback icon if input has visible label above - .has-feedback label { - - & ~ .molstar-form-control-feedback { - top: ($line-height-computed + 5); // Height of the `label` and its margin - } - &.sr-only ~ .molstar-form-control-feedback { - top: 0; - } - } - - - // Help text - // - // Apply to any element you wish to create light text for placement immediately - // below a form control. Use for general help, formatting, or instructional text. - - .help-block { - display: block; // account for any element using help-block - margin-top: 5px; - margin-bottom: 10px; - color: lighten($text-color, 25%); // lighten the text some for contrast - } - - - // Inline forms - // - // Make forms appear inline(-block) by adding the `.form-inline` class. Inline - // forms begin stacked on extra small (mobile) devices and then go inline when - // viewports reach <768px. - // - // Requires wrapping inputs and labels with `.form-group` for proper display of - // default HTML form controls and our custom form controls (e.g., input groups). - // - // Heads up! This is mixin-ed into `.navbar-form` in navbars.less. - - // [converter] extracted from `.form-inline` for libsass compatibility - @mixin form-inline { - - // Kick in the inline - @media (min-width: $screen-sm-min) { - // Inline-block all the things for "inline" - .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - - // In navbar-form, allow folks to *not* use `.form-group` - .molstar-form-control { - display: inline-block; - width: auto; // Prevent labels from stacking above inputs in `.form-group` - vertical-align: middle; - } - - // Make static controls behave like regular ones - .molstar-form-control-static { - display: inline-block; - } - - .input-group { - display: inline-table; - vertical-align: middle; - - .input-group-addon, - .input-group-molstar-btn, - .molstar-form-control { - width: auto; - } - } - - // Input groups need that 100% width though - .input-group > .molstar-form-control { - width: 100%; - } - - .control-label { - margin-bottom: 0; - vertical-align: middle; - } - - // Remove default margin on radios/checkboxes that were used for stacking, and - // then undo the floating of radios and checkboxes to match. - .radio, - .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - - label { - padding-left: 0; - } - } - .radio input[type="radio"], - .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - - // Re-override the feedback icon. - .has-feedback .molstar-form-control-feedback { - top: 0; - } - } - } - // [converter] extracted as `@mixin form-inline` for libsass compatibility - .form-inline { - @include form-inline; - } - - - - // Horizontal forms - // - // Horizontal forms are built on grid classes and allow you to create forms with - // labels on the left and inputs on the right. - - .form-horizontal { - - // Consistent vertical alignment of radios and checkboxes - // - // Labels also get some reset styles, but that is scoped to a media query below. - .radio, - .checkbox, - .radio-inline, - .checkbox-inline { - margin-top: 0; - margin-bottom: 0; - padding-top: ($padding-base-vertical + 1); // Default padding plus a border - } - // Account for padding we're adding to ensure the alignment and of help text - // and other content below items - .radio, - .checkbox { - min-height: ($line-height-computed + ($padding-base-vertical + 1)); - } - - // Make form groups behave like rows - .form-group { - @include make-row; - } - - // Reset spacing and right align labels, but scope to media queries so that - // labels on narrow viewports stack the same as a default form example. - @media (min-width: $screen-sm-min) { - .control-label { - text-align: right; - margin-bottom: 0; - padding-top: ($padding-base-vertical + 1); // Default padding plus a border - } - } - - // Validation states - // - // Reposition the icon because it's now within a grid column and columns have - // `position: relative;` on them. Also accounts for the grid gutter padding. - .has-feedback .molstar-form-control-feedback { - right: floor(($grid-gutter-width / 2)); - } - - // Form group sizes - // - // Quick utility class for applying `.input-lg` and `.input-sm` styles to the - // inputs and labels within a `.form-group`. - .form-group-lg { - @media (min-width: $screen-sm-min) { - .control-label { - padding-top: ($padding-large-vertical + 1); - font-size: $font-size-large; - } - } - } - .form-group-sm { - @media (min-width: $screen-sm-min) { - .control-label { - padding-top: ($padding-small-vertical + 1); - font-size: $font-size-small; - } - } - } - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/input-groups.scss b/src/mol-app/skin/bootstrap/input-groups.scss deleted file mode 100644 index 5f57fc3df5e9c92cc30cb750ccee0182d7df9bd9..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/input-groups.scss +++ /dev/null @@ -1,171 +0,0 @@ -// -// Input groups -// -------------------------------------------------- - -// Base styles -// ------------------------- -.input-group { - position: relative; // For dropdowns - display: table; - border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table - - // Undo padding and float of grid classes - &[class*="col-"] { - float: none; - padding-left: 0; - padding-right: 0; - } - - .molstar-form-control { - // Ensure that the input is always above the *appended* addon button for - // proper border colors. - position: relative; - z-index: 2; - - // IE9 fubars the placeholder attribute in text inputs and the arrows on - // select elements in input groups. To fix it, we float the input. Details: - // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855 - float: left; - - width: 100%; - margin-bottom: 0; - - &:focus { - z-index: 3; - } - } - } - - // Sizing options - // - // Remix the default form control sizing classes into new ones for easier - // manipulation. - - .input-group-lg > .molstar-form-control, - .input-group-lg > .input-group-addon, - .input-group-lg > .input-group-molstar-btn > .molstar-btn { - @extend .input-lg; - } - .input-group-sm > .molstar-form-control, - .input-group-sm > .input-group-addon, - .input-group-sm > .input-group-molstar-btn > .molstar-btn { - @extend .input-sm; - } - - - // Display as table-cell - // ------------------------- - .input-group-addon, - .input-group-molstar-btn, - .input-group .molstar-form-control { - display: table-cell; - - &:not(:first-child):not(:last-child) { - border-radius: 0; - } - } - // Addon and addon wrapper for buttons - .input-group-addon, - .input-group-molstar-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; // Match the inputs - } - - // Text input groups - // ------------------------- - .input-group-addon { - padding: $padding-base-vertical $padding-base-horizontal; - font-size: $font-size-base; - font-weight: normal; - line-height: 1; - color: $input-color; - text-align: center; - background-color: $input-group-addon-bg; - border: 1px solid $input-group-addon-border-color; - border-radius: $input-border-radius; - - // Sizing - &.input-sm { - padding: $padding-small-vertical $padding-small-horizontal; - font-size: $font-size-small; - border-radius: $input-border-radius-small; - } - &.input-lg { - padding: $padding-large-vertical $padding-large-horizontal; - font-size: $font-size-large; - border-radius: $input-border-radius-large; - } - - // Nuke default margins from checkboxes and radios to vertically center within. - input[type="radio"], - input[type="checkbox"] { - margin-top: 0; - } - } - - // Reset rounded corners - .input-group .molstar-form-control:first-child, - .input-group-addon:first-child, - .input-group-molstar-btn:first-child > .molstar-btn, - .input-group-molstar-btn:first-child > .molstar-btn-group > .molstar-btn, - .input-group-molstar-btn:first-child > .dropdown-toggle, - .input-group-molstar-btn:last-child > .molstar-btn:not(:last-child):not(.dropdown-toggle), - .input-group-molstar-btn:last-child > .molstar-btn-group:not(:last-child) > .molstar-btn { - @include border-right-radius(0); - } - .input-group-addon:first-child { - border-right: 0; - } - .input-group .molstar-form-control:last-child, - .input-group-addon:last-child, - .input-group-molstar-btn:last-child > .molstar-btn, - .input-group-molstar-btn:last-child > .molstar-btn-group > .molstar-btn, - .input-group-molstar-btn:last-child > .dropdown-toggle, - .input-group-molstar-btn:first-child > .molstar-btn:not(:first-child), - .input-group-molstar-btn:first-child > .molstar-btn-group:not(:first-child) > .molstar-btn { - @include border-left-radius(0); - } - .input-group-addon:last-child { - border-left: 0; - } - - // Button input groups - // ------------------------- - .input-group-molstar-btn { - position: relative; - // Jankily prevent input button groups from wrapping with `white-space` and - // `font-size` in combination with `inline-block` on buttons. - font-size: 0; - white-space: nowrap; - - // Negative margin for spacing, position for bringing hovered/focused/actived - // element above the siblings. - > .molstar-btn { - position: relative; - + .molstar-btn { - margin-left: -1px; - } - // Bring the "active" button to the front - &:hover, - &:focus, - &:active { - z-index: 2; - } - } - - // Negative margin to only have a 1px border between the two - &:first-child { - > .molstar-btn, - > .molstar-btn-group { - margin-right: -1px; - } - } - &:last-child { - > .molstar-btn, - > .molstar-btn-group { - z-index: 2; - margin-left: -1px; - } - } - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/labels.scss b/src/mol-app/skin/bootstrap/labels.scss deleted file mode 100644 index c453cd4173c362721e629c88e94c4de362b07fa1..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/labels.scss +++ /dev/null @@ -1,66 +0,0 @@ -// -// Labels -// -------------------------------------------------- - -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: $label-color; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; - - // [converter] extracted a& to a.label - - // Empty labels collapse automatically (not available in IE8) - &:empty { - display: none; - } - - // Quick fix for labels in buttons - .molstar-btn & { - position: relative; - top: -1px; - } - } - - // Add hover effects, but only for links - a.label { - &:hover, - &:focus { - color: $label-link-hover-color; - text-decoration: none; - cursor: pointer; - } - } - - // Colors - // Contextual variations (linked labels get darker on :hover) - - .label-default { - @include label-variant($label-default-bg); - } - - .label-primary { - @include label-variant($label-primary-bg); - } - - .label-success { - @include label-variant($label-success-bg); - } - - .label-info { - @include label-variant($label-info-bg); - } - - .label-warning { - @include label-variant($label-warning-bg); - } - - .label-danger { - @include label-variant($label-danger-bg); - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins.scss b/src/mol-app/skin/bootstrap/mixins.scss deleted file mode 100644 index 94b12fed20092a647d8ceaa9a0ad700f6bbad65a..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins.scss +++ /dev/null @@ -1,40 +0,0 @@ -// Mixins -// -------------------------------------------------- - -// Utilities -// @import "mixins/hide-text"; -@import "mixins/opacity"; -@import "mixins/image"; -@import "mixins/labels"; -// @import "mixins/reset-filter"; -// @import "mixins/resize"; -// @import "mixins/responsive-visibility"; -// @import "mixins/size"; -@import "mixins/tab-focus"; -// @import "mixins/reset-text"; -@import "mixins/text-emphasis"; -@import "mixins/text-overflow"; -@import "mixins/vendor-prefixes"; - -// Components -// @import "mixins/alerts"; -@import "mixins/buttons"; -// @import "mixins/panels"; -// @import "mixins/pagination"; -// @import "mixins/list-group"; -// @import "mixins/nav-divider"; -@import "mixins/forms"; -// @import "mixins/progress-bar"; -// @import "mixins/table-row"; - -// Skins -@import "mixins/background-variant"; -@import "mixins/border-radius"; -// @import "mixins/gradients"; - -// Layout -@import "mixins/clearfix"; -// @import "mixins/center-block"; -// @import "mixins/nav-vertical-align"; -// @import "mixins/grid-framework"; -@import "mixins/grid"; \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/background-variant.scss b/src/mol-app/skin/bootstrap/mixins/background-variant.scss deleted file mode 100644 index a3044fff2190918a3f09b8ae795b78a5f45316a0..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/background-variant.scss +++ /dev/null @@ -1,12 +0,0 @@ -// Contextual backgrounds - -// [converter] $parent hack -@mixin bg-variant($parent, $color) { - #{$parent} { - background-color: $color; - } - a#{$parent}:hover, - a#{$parent}:focus { - background-color: darken($color, 10%); - } -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/border-radius.scss b/src/mol-app/skin/bootstrap/mixins/border-radius.scss deleted file mode 100644 index 2ba5d06e81ad3301f657b07e05ed8b9d9e604770..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/border-radius.scss +++ /dev/null @@ -1,18 +0,0 @@ -// Single side border-radius - -@mixin border-top-radius($radius) { - border-top-right-radius: $radius; - border-top-left-radius: $radius; -} -@mixin border-right-radius($radius) { - border-bottom-right-radius: $radius; - border-top-right-radius: $radius; -} -@mixin border-bottom-radius($radius) { - border-bottom-right-radius: $radius; - border-bottom-left-radius: $radius; -} -@mixin border-left-radius($radius) { - border-bottom-left-radius: $radius; - border-top-left-radius: $radius; -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/buttons.scss b/src/mol-app/skin/bootstrap/mixins/buttons.scss deleted file mode 100644 index c7be1237a5c12b198cd90091617e9bacb0107a62..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/buttons.scss +++ /dev/null @@ -1,65 +0,0 @@ -// Button variants -// -// Easily pump out default styles, as well as :hover, :focus, :active, -// and disabled options for all buttons - -@mixin button-variant($color, $background, $border) { - color: $color; - background-color: $background; - border-color: $border; - - &:focus, - &.focus { - color: $color; - background-color: darken($background, 10%); - border-color: darken($border, 25%); - } - &:hover { - color: $color; - background-color: darken($background, 10%); - border-color: darken($border, 12%); - } - &:active, - &.active, - .open > &.dropdown-toggle { - color: $color; - background-color: darken($background, 10%); - border-color: darken($border, 12%); - - &:hover, - &:focus, - &.focus { - color: $color; - background-color: darken($background, 17%); - border-color: darken($border, 25%); - } - } - &:active, - &.active, - .open > &.dropdown-toggle { - background-image: none; - } - &.disabled, - &[disabled], - fieldset[disabled] & { - &:hover, - &:focus, - &.focus { - background-color: $background; - border-color: $border; - } - } - - .badge { - color: $background; - background-color: $color; - } - } - - // Button sizes - @mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) { - padding: $padding-vertical $padding-horizontal; - font-size: $font-size; - line-height: $line-height; - border-radius: $border-radius; - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/clearfix.scss b/src/mol-app/skin/bootstrap/mixins/clearfix.scss deleted file mode 100644 index 12d42afa77016633e70bc238c2dd741129abf2f7..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/clearfix.scss +++ /dev/null @@ -1,22 +0,0 @@ -// Clearfix -// -// For modern browsers -// 1. The space content is one way to avoid an Opera bug when the -// contenteditable attribute is included anywhere else in the document. -// Otherwise it causes space to appear at the top and bottom of elements -// that are clearfixed. -// 2. The use of `table` rather than `block` is only necessary if using -// `:before` to contain the top-margins of child elements. -// -// Source: http://nicolasgallagher.com/micro-clearfix-hack/ - -@mixin clearfix() { - &:before, - &:after { - content: " "; // 1 - display: table; // 2 - } - &:after { - clear: both; - } -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/forms.scss b/src/mol-app/skin/bootstrap/mixins/forms.scss deleted file mode 100644 index 2bfe4f00a75b7a0132a9412698bbdf7cf2e1cc47..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/forms.scss +++ /dev/null @@ -1,88 +0,0 @@ -// Form validation states -// -// Used in forms.less to generate the form validation CSS for warnings, errors, -// and successes. - -@mixin molstar-form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) { - // Color the label and help text - .help-block, - .control-label, - .radio, - .checkbox, - .radio-inline, - .checkbox-inline, - &.radio label, - &.checkbox label, - &.radio-inline label, - &.checkbox-inline label { - color: $text-color; - } - // Set the border and box shadow on specific inputs to match - .molstar-form-control { - border-color: $border-color; - @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work - &:focus { - border-color: darken($border-color, 10%); - $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%); - @include box-shadow($shadow); - } - } - // Set validation states also for addons - .input-group-addon { - color: $text-color; - border-color: $border-color; - background-color: $background-color; - } - // Optional feedback icon - .molstar-form-control-feedback { - color: $text-color; - } - } - - - // Form control focus state - // - // Generate a customized focus state and for any input with the specified color, - // which defaults to the `$input-border-focus` variable. - // - // We highly encourage you to not customize the default value, but instead use - // this to tweak colors on an as-needed basis. This aesthetic change is based on - // WebKit's default styles, but applicable to a wider range of browsers. Its - // usability and accessibility should be taken into account with any change. - // - // Example usage: change the default blue border and shadow to white for better - // contrast against a dark gray background. - @mixin molstar-form-control-focus($color: $input-border-focus) { - $color-rgba: rgba(red($color), green($color), blue($color), .6); - &:focus { - border-color: $color; - outline: 0; - @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba); - } - } - - // Form control sizing - // - // Relative text size, padding, and border-radii changes for form controls. For - // horizontal sizing, wrap controls in the predefined grid classes. `<select>` - // element gets special love because it's special, and that's a fact! - // [converter] $parent hack - @mixin input-size($parent, $input-height, $padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) { - #{$parent} { - height: $input-height; - padding: $padding-vertical $padding-horizontal; - font-size: $font-size; - line-height: $line-height; - border-radius: $border-radius; - } - - select#{$parent} { - height: $input-height; - line-height: $input-height; - } - - textarea#{$parent}, - select[multiple]#{$parent} { - height: auto; - } - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/grid.scss b/src/mol-app/skin/bootstrap/mixins/grid.scss deleted file mode 100644 index 7457a0abaa5f59fd4a8128f969d61de347e315e7..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/grid.scss +++ /dev/null @@ -1,122 +0,0 @@ -// Grid system -// -// Generate semantic grid columns with these mixins. - -// Centered container element -@mixin container-fixed($gutter: $grid-gutter-width) { - margin-right: auto; - margin-left: auto; - padding-left: floor(($gutter / 2)); - padding-right: ceil(($gutter / 2)); - @include clearfix; - } - - // Creates a wrapper for a series of columns - @mixin make-row($gutter: $grid-gutter-width) { - margin-left: ceil(($gutter / -2)); - margin-right: floor(($gutter / -2)); - @include clearfix; - } - - // Generate the extra small columns - @mixin make-xs-column($columns, $gutter: $grid-gutter-width) { - position: relative; - float: left; - width: percentage(($columns / $grid-columns)); - min-height: 1px; - padding-left: ($gutter / 2); - padding-right: ($gutter / 2); - } - @mixin make-xs-column-offset($columns) { - margin-left: percentage(($columns / $grid-columns)); - } - @mixin make-xs-column-push($columns) { - left: percentage(($columns / $grid-columns)); - } - @mixin make-xs-column-pull($columns) { - right: percentage(($columns / $grid-columns)); - } - - // Generate the small columns - @mixin make-sm-column($columns, $gutter: $grid-gutter-width) { - position: relative; - min-height: 1px; - padding-left: ($gutter / 2); - padding-right: ($gutter / 2); - - @media (min-width: $screen-sm-min) { - float: left; - width: percentage(($columns / $grid-columns)); - } - } - @mixin make-sm-column-offset($columns) { - @media (min-width: $screen-sm-min) { - margin-left: percentage(($columns / $grid-columns)); - } - } - @mixin make-sm-column-push($columns) { - @media (min-width: $screen-sm-min) { - left: percentage(($columns / $grid-columns)); - } - } - @mixin make-sm-column-pull($columns) { - @media (min-width: $screen-sm-min) { - right: percentage(($columns / $grid-columns)); - } - } - - // Generate the medium columns - @mixin make-md-column($columns, $gutter: $grid-gutter-width) { - position: relative; - min-height: 1px; - padding-left: ($gutter / 2); - padding-right: ($gutter / 2); - - @media (min-width: $screen-md-min) { - float: left; - width: percentage(($columns / $grid-columns)); - } - } - @mixin make-md-column-offset($columns) { - @media (min-width: $screen-md-min) { - margin-left: percentage(($columns / $grid-columns)); - } - } - @mixin make-md-column-push($columns) { - @media (min-width: $screen-md-min) { - left: percentage(($columns / $grid-columns)); - } - } - @mixin make-md-column-pull($columns) { - @media (min-width: $screen-md-min) { - right: percentage(($columns / $grid-columns)); - } - } - - // Generate the large columns - @mixin make-lg-column($columns, $gutter: $grid-gutter-width) { - position: relative; - min-height: 1px; - padding-left: ($gutter / 2); - padding-right: ($gutter / 2); - - @media (min-width: $screen-lg-min) { - float: left; - width: percentage(($columns / $grid-columns)); - } - } - @mixin make-lg-column-offset($columns) { - @media (min-width: $screen-lg-min) { - margin-left: percentage(($columns / $grid-columns)); - } - } - @mixin make-lg-column-push($columns) { - @media (min-width: $screen-lg-min) { - left: percentage(($columns / $grid-columns)); - } - } - @mixin make-lg-column-pull($columns) { - @media (min-width: $screen-lg-min) { - right: percentage(($columns / $grid-columns)); - } - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/image.scss b/src/mol-app/skin/bootstrap/mixins/image.scss deleted file mode 100644 index 608cad5a535bf7db769366eef99d77c39a7283a2..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/image.scss +++ /dev/null @@ -1,33 +0,0 @@ -// Image Mixins -// - Responsive image -// - Retina image - - -// Responsive image -// -// Keep images from scaling beyond the width of their parents. -@mixin img-responsive($display: block) { - display: $display; - max-width: 100%; // Part 1: Set a maximum relative to the parent - height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching -} - - -// Retina image -// -// Short retina mixin for setting background-image and -size. Note that the -// spelling of `min--moz-device-pixel-ratio` is intentional. -@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) { - background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-1x}"), "#{$file-1x}")); - - @media - only screen and (-webkit-min-device-pixel-ratio: 2), - only screen and ( min--moz-device-pixel-ratio: 2), - only screen and ( -o-min-device-pixel-ratio: 2/1), - only screen and ( min-device-pixel-ratio: 2), - only screen and ( min-resolution: 192dpi), - only screen and ( min-resolution: 2dppx) { - background-image: url(if($bootstrap-sass-asset-helper, twbs-image-path("#{$file-2x}"), "#{$file-2x}")); - background-size: $width-1x $height-1x; - } -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/labels.scss b/src/mol-app/skin/bootstrap/mixins/labels.scss deleted file mode 100644 index 1353b098dd8d4f89ff79da862d9e856f52dd674a..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/labels.scss +++ /dev/null @@ -1,12 +0,0 @@ -// Labels - -@mixin label-variant($color) { - background-color: $color; - - &[href] { - &:hover, - &:focus { - background-color: darken($color, 10%); - } - } -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/opacity.scss b/src/mol-app/skin/bootstrap/mixins/opacity.scss deleted file mode 100644 index f04356c6bb431f3c7f6e027e070fd1b39018c055..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/opacity.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Opacity - -@mixin opacity($opacity) { - opacity: $opacity; - // IE8 filter - $opacity-ie: ($opacity * 100); - filter: alpha(opacity=$opacity-ie); -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/tab-focus.scss b/src/mol-app/skin/bootstrap/mixins/tab-focus.scss deleted file mode 100644 index 414babf68561d780f937be3e206fd8ea7a49f160..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/tab-focus.scss +++ /dev/null @@ -1,9 +0,0 @@ -// WebKit-style focus - -@mixin tab-focus() { - // Default - outline: thin dotted; - // WebKit - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/text-emphasis.scss b/src/mol-app/skin/bootstrap/mixins/text-emphasis.scss deleted file mode 100644 index dddb9ae2521c23982487c603f8606cc7c7d5495a..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/text-emphasis.scss +++ /dev/null @@ -1,12 +0,0 @@ -// Typography - -// [converter] $parent hack -@mixin text-emphasis-variant($parent, $color) { - #{$parent} { - color: $color; - } - a#{$parent}:hover, - a#{$parent}:focus { - color: darken($color, 10%); - } -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/text-overflow.scss b/src/mol-app/skin/bootstrap/mixins/text-overflow.scss deleted file mode 100644 index b6ac5f707d4779f51d55e9657dc24e2a4e6cc77f..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/text-overflow.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Text overflow -// Requires inline-block or block for proper styling - -@mixin text-overflow() { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/mixins/vendor-prefixes.scss b/src/mol-app/skin/bootstrap/mixins/vendor-prefixes.scss deleted file mode 100644 index b657e7a26ef78da22d21d1a3a84b337d8b7463d0..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/mixins/vendor-prefixes.scss +++ /dev/null @@ -1,222 +0,0 @@ -// Vendor Prefixes -// -// All vendor mixins are deprecated as of v3.2.0 due to the introduction of -// Autoprefixer in our Gruntfile. They have been removed in v4. - -// - Animations -// - Backface visibility -// - Box shadow -// - Box sizing -// - Content columns -// - Hyphens -// - Placeholder text -// - Transformations -// - Transitions -// - User Select - - -// Animations -@mixin animation($animation) { - -webkit-animation: $animation; - -o-animation: $animation; - animation: $animation; - } - @mixin animation-name($name) { - -webkit-animation-name: $name; - animation-name: $name; - } - @mixin animation-duration($duration) { - -webkit-animation-duration: $duration; - animation-duration: $duration; - } - @mixin animation-timing-function($timing-function) { - -webkit-animation-timing-function: $timing-function; - animation-timing-function: $timing-function; - } - @mixin animation-delay($delay) { - -webkit-animation-delay: $delay; - animation-delay: $delay; - } - @mixin animation-iteration-count($iteration-count) { - -webkit-animation-iteration-count: $iteration-count; - animation-iteration-count: $iteration-count; - } - @mixin animation-direction($direction) { - -webkit-animation-direction: $direction; - animation-direction: $direction; - } - @mixin animation-fill-mode($fill-mode) { - -webkit-animation-fill-mode: $fill-mode; - animation-fill-mode: $fill-mode; - } - - // Backface visibility - // Prevent browsers from flickering when using CSS 3D transforms. - // Default value is `visible`, but can be changed to `hidden` - - @mixin backface-visibility($visibility) { - -webkit-backface-visibility: $visibility; - -moz-backface-visibility: $visibility; - backface-visibility: $visibility; - } - - // Drop shadows - // - // Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's - // supported browsers that have box shadow capabilities now support it. - - @mixin box-shadow($shadow...) { - -webkit-box-shadow: $shadow; // iOS <4.3 & Android <4.1 - box-shadow: $shadow; - } - - // Box sizing - @mixin box-sizing($boxmodel) { - -webkit-box-sizing: $boxmodel; - -moz-box-sizing: $boxmodel; - box-sizing: $boxmodel; - } - - // CSS3 Content Columns - @mixin content-columns($column-count, $column-gap: $grid-gutter-width) { - -webkit-column-count: $column-count; - -moz-column-count: $column-count; - column-count: $column-count; - -webkit-column-gap: $column-gap; - -moz-column-gap: $column-gap; - column-gap: $column-gap; - } - - // Optional hyphenation - @mixin hyphens($mode: auto) { - word-wrap: break-word; - -webkit-hyphens: $mode; - -moz-hyphens: $mode; - -ms-hyphens: $mode; // IE10+ - -o-hyphens: $mode; - hyphens: $mode; - } - - // Placeholder text - @mixin placeholder($color: $input-color-placeholder) { - // Firefox - &::-moz-placeholder { - color: $color; - opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526 - } - &:-ms-input-placeholder { color: $color; } // Internet Explorer 10+ - &::-webkit-input-placeholder { color: $color; } // Safari and Chrome - } - - // Transformations - @mixin scale($ratio...) { - -webkit-transform: scale($ratio); - -ms-transform: scale($ratio); // IE9 only - -o-transform: scale($ratio); - transform: scale($ratio); - } - - @mixin scaleX($ratio) { - -webkit-transform: scaleX($ratio); - -ms-transform: scaleX($ratio); // IE9 only - -o-transform: scaleX($ratio); - transform: scaleX($ratio); - } - @mixin scaleY($ratio) { - -webkit-transform: scaleY($ratio); - -ms-transform: scaleY($ratio); // IE9 only - -o-transform: scaleY($ratio); - transform: scaleY($ratio); - } - @mixin skew($x, $y) { - -webkit-transform: skewX($x) skewY($y); - -ms-transform: skewX($x) skewY($y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+ - -o-transform: skewX($x) skewY($y); - transform: skewX($x) skewY($y); - } - @mixin translate($x, $y) { - -webkit-transform: translate($x, $y); - -ms-transform: translate($x, $y); // IE9 only - -o-transform: translate($x, $y); - transform: translate($x, $y); - } - @mixin translate3d($x, $y, $z) { - -webkit-transform: translate3d($x, $y, $z); - transform: translate3d($x, $y, $z); - } - @mixin rotate($degrees) { - -webkit-transform: rotate($degrees); - -ms-transform: rotate($degrees); // IE9 only - -o-transform: rotate($degrees); - transform: rotate($degrees); - } - @mixin rotateX($degrees) { - -webkit-transform: rotateX($degrees); - -ms-transform: rotateX($degrees); // IE9 only - -o-transform: rotateX($degrees); - transform: rotateX($degrees); - } - @mixin rotateY($degrees) { - -webkit-transform: rotateY($degrees); - -ms-transform: rotateY($degrees); // IE9 only - -o-transform: rotateY($degrees); - transform: rotateY($degrees); - } - @mixin perspective($perspective) { - -webkit-perspective: $perspective; - -moz-perspective: $perspective; - perspective: $perspective; - } - @mixin perspective-origin($perspective) { - -webkit-perspective-origin: $perspective; - -moz-perspective-origin: $perspective; - perspective-origin: $perspective; - } - @mixin transform-origin($origin) { - -webkit-transform-origin: $origin; - -moz-transform-origin: $origin; - -ms-transform-origin: $origin; // IE9 only - transform-origin: $origin; - } - - - // Transitions - - @mixin transition($transition...) { - -webkit-transition: $transition; - -o-transition: $transition; - transition: $transition; - } - @mixin transition-property($transition-property...) { - -webkit-transition-property: $transition-property; - transition-property: $transition-property; - } - @mixin transition-delay($transition-delay) { - -webkit-transition-delay: $transition-delay; - transition-delay: $transition-delay; - } - @mixin transition-duration($transition-duration...) { - -webkit-transition-duration: $transition-duration; - transition-duration: $transition-duration; - } - @mixin transition-timing-function($timing-function) { - -webkit-transition-timing-function: $timing-function; - transition-timing-function: $timing-function; - } - @mixin transition-transform($transition...) { - -webkit-transition: -webkit-transform $transition; - -moz-transition: -moz-transform $transition; - -o-transition: -o-transform $transition; - transition: transform $transition; - } - - - // User select - // For selecting text on the page - - @mixin user-select($select) { - -webkit-user-select: $select; - -moz-user-select: $select; - -ms-user-select: $select; // IE10+ - user-select: $select; - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/normalize.scss b/src/mol-app/skin/bootstrap/normalize.scss deleted file mode 100644 index 7caf32b8c46f2f2926cdd3f4b86e91fdcf0e425f..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/normalize.scss +++ /dev/null @@ -1,424 +0,0 @@ -/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ - -// -// 1. Set default font family to sans-serif. -// 2. Prevent iOS and IE text size adjust after device orientation change, -// without disabling user zoom. -// - -html { - font-family: sans-serif; // 1 - -ms-text-size-adjust: 100%; // 2 - -webkit-text-size-adjust: 100%; // 2 - } - - // - // Remove default margin. - // - - body { - margin: 0; - } - - // HTML5 display definitions - // ========================================================================== - - // - // Correct `block` display not defined for any HTML5 element in IE 8/9. - // Correct `block` display not defined for `details` or `summary` in IE 10/11 - // and Firefox. - // Correct `block` display not defined for `main` in IE 11. - // - - article, - aside, - details, - figcaption, - figure, - footer, - header, - hgroup, - main, - menu, - nav, - section, - summary { - display: block; - } - - // - // 1. Correct `inline-block` display not defined in IE 8/9. - // 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. - // - - audio, - canvas, - progress, - video { - display: inline-block; // 1 - vertical-align: baseline; // 2 - } - - // - // Prevent modern browsers from displaying `audio` without controls. - // Remove excess height in iOS 5 devices. - // - - audio:not([controls]) { - display: none; - height: 0; - } - - // - // Address `[hidden]` styling not present in IE 8/9/10. - // Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. - // - - [hidden], - template { - display: none; - } - - // Links - // ========================================================================== - - // - // Remove the gray background color from active links in IE 10. - // - - a { - background-color: transparent; - } - - // - // Improve readability of focused elements when they are also in an - // active/hover state. - // - - a:active, - a:hover { - outline: 0; - } - - // Text-level semantics - // ========================================================================== - - // - // Address styling not present in IE 8/9/10/11, Safari, and Chrome. - // - - abbr[title] { - border-bottom: 1px dotted; - } - - // - // Address style set to `bolder` in Firefox 4+, Safari, and Chrome. - // - - b, - strong { - font-weight: bold; - } - - // - // Address styling not present in Safari and Chrome. - // - - dfn { - font-style: italic; - } - - // - // Address variable `h1` font-size and margin within `section` and `article` - // contexts in Firefox 4+, Safari, and Chrome. - // - - h1 { - font-size: 2em; - margin: 0.67em 0; - } - - // - // Address styling not present in IE 8/9. - // - - mark { - background: #ff0; - color: #000; - } - - // - // Address inconsistent and variable font size in all browsers. - // - - small { - font-size: 80%; - } - - // - // Prevent `sub` and `sup` affecting `line-height` in all browsers. - // - - sub, - sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; - } - - sup { - top: -0.5em; - } - - sub { - bottom: -0.25em; - } - - // Embedded content - // ========================================================================== - - // - // Remove border when inside `a` element in IE 8/9/10. - // - - img { - border: 0; - } - - // - // Correct overflow not hidden in IE 9/10/11. - // - - svg:not(:root) { - overflow: hidden; - } - - // Grouping content - // ========================================================================== - - // - // Address margin not present in IE 8/9 and Safari. - // - - figure { - margin: 1em 40px; - } - - // - // Address differences between Firefox and other browsers. - // - - hr { - box-sizing: content-box; - height: 0; - } - - // - // Contain overflow in all browsers. - // - - pre { - overflow: auto; - } - - // - // Address odd `em`-unit font size rendering in all browsers. - // - - code, - kbd, - pre, - samp { - font-family: monospace, monospace; - font-size: 1em; - } - - // Forms - // ========================================================================== - - // - // Known limitation: by default, Chrome and Safari on OS X allow very limited - // styling of `select`, unless a `border` property is set. - // - - // - // 1. Correct color not being inherited. - // Known issue: affects color of disabled elements. - // 2. Correct font properties not being inherited. - // 3. Address margins set differently in Firefox 4+, Safari, and Chrome. - // - - button, - input, - optgroup, - select, - textarea { - color: inherit; // 1 - font: inherit; // 2 - margin: 0; // 3 - } - - // - // Address `overflow` set to `hidden` in IE 8/9/10/11. - // - - button { - overflow: visible; - } - - // - // Address inconsistent `text-transform` inheritance for `button` and `select`. - // All other form control elements do not inherit `text-transform` values. - // Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. - // Correct `select` style inheritance in Firefox. - // - - button, - select { - text-transform: none; - } - - // - // 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` - // and `video` controls. - // 2. Correct inability to style clickable `input` types in iOS. - // 3. Improve usability and consistency of cursor style between image-type - // `input` and others. - // - - button, - html input[type="button"], // 1 - input[type="reset"], - input[type="submit"] { - -webkit-appearance: button; // 2 - cursor: pointer; // 3 - } - - // - // Re-set default cursor for disabled elements. - // - - button[disabled], - html input[disabled] { - cursor: default; - } - - // - // Remove inner padding and border in Firefox 4+. - // - - button::-moz-focus-inner, - input::-moz-focus-inner { - border: 0; - padding: 0; - } - - // - // Address Firefox 4+ setting `line-height` on `input` using `!important` in - // the UA stylesheet. - // - - input { - line-height: normal; - } - - // - // It's recommended that you don't attempt to style these elements. - // Firefox's implementation doesn't respect box-sizing, padding, or width. - // - // 1. Address box sizing set to `content-box` in IE 8/9/10. - // 2. Remove excess padding in IE 8/9/10. - // - - input[type="checkbox"], - input[type="radio"] { - box-sizing: border-box; // 1 - padding: 0; // 2 - } - - // - // Fix the cursor style for Chrome's increment/decrement buttons. For certain - // `font-size` values of the `input`, it causes the cursor style of the - // decrement button to change from `default` to `text`. - // - - input[type="number"]::-webkit-inner-spin-button, - input[type="number"]::-webkit-outer-spin-button { - height: auto; - } - - // - // 1. Address `appearance` set to `searchfield` in Safari and Chrome. - // 2. Address `box-sizing` set to `border-box` in Safari and Chrome. - // - - input[type="search"] { - -webkit-appearance: textfield; // 1 - box-sizing: content-box; //2 - } - - // - // Remove inner padding and search cancel button in Safari and Chrome on OS X. - // Safari (but not Chrome) clips the cancel button when the search input has - // padding (and `textfield` appearance). - // - - input[type="search"]::-webkit-search-cancel-button, - input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; - } - - // - // Define consistent border, margin, and padding. - // - - fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; - } - - // - // 1. Correct `color` not being inherited in IE 8/9/10/11. - // 2. Remove padding so people aren't caught out if they zero out fieldsets. - // - - legend { - border: 0; // 1 - padding: 0; // 2 - } - - // - // Remove default vertical scrollbar in IE 8/9/10/11. - // - - textarea { - overflow: auto; - } - - // - // Don't inherit the `font-weight` (applied by a rule above). - // NOTE: the default cannot safely be changed in Chrome and Safari on OS X. - // - - optgroup { - font-weight: bold; - } - - // Tables - // ========================================================================== - - // - // Remove most spacing between table cells. - // - - table { - border-collapse: collapse; - border-spacing: 0; - } - - td, - th { - padding: 0; - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/scaffolding.scss b/src/mol-app/skin/bootstrap/scaffolding.scss deleted file mode 100644 index 556b6acdfe77bec08b388e8ecf27bf86633fe3f9..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/scaffolding.scss +++ /dev/null @@ -1,161 +0,0 @@ -// -// Scaffolding -// -------------------------------------------------- - - -// Reset the box-sizing -// -// Heads up! This reset may cause conflicts with some third-party widgets. -// For recommendations on resolving such conflicts, see -// http://getbootstrap.com/getting-started/#third-box-sizing -* { - @include box-sizing(border-box); - } - *:before, - *:after { - @include box-sizing(border-box); - } - - - // Body reset - - html { - font-size: 10px; - -webkit-tap-highlight-color: rgba(0,0,0,0); - } - - body { - font-family: $font-family-base; - font-size: $font-size-base; - line-height: $line-height-base; - color: $text-color; - background-color: $body-bg; - } - - // Reset fonts for relevant elements - input, - button, - select, - textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; - } - - - // Links - - a { - color: $link-color; - text-decoration: none; - - &:hover, - &:focus { - color: $link-hover-color; - text-decoration: $link-hover-decoration; - } - - &:focus { - @include tab-focus; - } - } - - - // Figures - // - // We reset this here because previously Normalize had no `figure` margins. This - // ensures we don't break anyone's use of the element. - - figure { - margin: 0; - } - - - // Images - - img { - vertical-align: middle; - } - - // Responsive images (ensure images don't scale beyond their parents) - .img-responsive { - @include img-responsive; - } - - // Rounded corners - .img-rounded { - border-radius: $border-radius-large; - } - - // Image thumbnails - // - // Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`. - .img-thumbnail { - padding: $thumbnail-padding; - line-height: $line-height-base; - background-color: $thumbnail-bg; - border: 1px solid $thumbnail-border; - border-radius: $thumbnail-border-radius; - @include transition(all .2s ease-in-out); - - // Keep them at most 100% wide - @include img-responsive(inline-block); - } - - // Perfect circle - .img-circle { - border-radius: 50%; // set radius in percents - } - - - // Horizontal rules - - hr { - margin-top: $line-height-computed; - margin-bottom: $line-height-computed; - border: 0; - border-top: 1px solid $hr-border; - } - - - // Only display content to screen readers - // - // See: http://a11yproject.com/posts/how-to-hide-content/ - - .sr-only { - position: absolute; - width: 1px; - height: 1px; - margin: -1px; - padding: 0; - overflow: hidden; - clip: rect(0,0,0,0); - border: 0; - } - - // Use in conjunction with .sr-only to only display content when it's focused. - // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 - // Credit: HTML5 Boilerplate - - .sr-only-focusable { - &:active, - &:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; - } - } - - - // iOS "clickable elements" fix for role="button" - // - // Fixes "clickability" issue (and more generally, the firing of events such as focus as well) - // for traditionally non-focusable elements with role="button" - // see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile - - [role="button"] { - cursor: pointer; - } \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/type.scss b/src/mol-app/skin/bootstrap/type.scss deleted file mode 100644 index 92c0b63cac4e9c378be6c6fa1a41960fb5269634..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/type.scss +++ /dev/null @@ -1,298 +0,0 @@ -// -// Typography -// -------------------------------------------------- - - -// Headings -// ------------------------- - -h1, h2, h3, h4, h5, h6, -.h1, .h2, .h3, .h4, .h5, .h6 { - font-family: $headings-font-family; - font-weight: $headings-font-weight; - line-height: $headings-line-height; - color: $headings-color; - - small, - .small { - font-weight: normal; - line-height: 1; - color: $headings-small-color; - } -} - -h1, .h1, -h2, .h2, -h3, .h3 { - margin-top: $line-height-computed; - margin-bottom: ($line-height-computed / 2); - - small, - .small { - font-size: 65%; - } -} -h4, .h4, -h5, .h5, -h6, .h6 { - margin-top: ($line-height-computed / 2); - margin-bottom: ($line-height-computed / 2); - - small, - .small { - font-size: 75%; - } -} - -h1, .h1 { font-size: $font-size-h1; } -h2, .h2 { font-size: $font-size-h2; } -h3, .h3 { font-size: $font-size-h3; } -h4, .h4 { font-size: $font-size-h4; } -h5, .h5 { font-size: $font-size-h5; } -h6, .h6 { font-size: $font-size-h6; } - - -// Body text -// ------------------------- - -p { - margin: 0 0 ($line-height-computed / 2); -} - -.lead { - margin-bottom: $line-height-computed; - font-size: floor(($font-size-base * 1.15)); - font-weight: 300; - line-height: 1.4; - - @media (min-width: $screen-sm-min) { - font-size: ($font-size-base * 1.5); - } -} - - -// Emphasis & misc -// ------------------------- - -// Ex: (12px small font / 14px base font) * 100% = about 85% -small, -.small { - font-size: floor((100% * $font-size-small / $font-size-base)); -} - -mark, -.mark { - background-color: $state-warning-bg; - padding: .2em; -} - -// Alignment -.text-left { text-align: left; } -.text-right { text-align: right; } -.text-center { text-align: center; } -.text-justify { text-align: justify; } -.text-nowrap { white-space: nowrap; } - -// Transformation -.text-lowercase { text-transform: lowercase; } -.text-uppercase { text-transform: uppercase; } -.text-capitalize { text-transform: capitalize; } - -// Contextual colors -.text-muted { - color: $text-muted; -} - -@include text-emphasis-variant('.text-primary', $brand-primary); - -@include text-emphasis-variant('.text-success', $state-success-text); - -@include text-emphasis-variant('.text-info', $state-info-text); - -@include text-emphasis-variant('.text-warning', $state-warning-text); - -@include text-emphasis-variant('.text-danger', $state-danger-text); - -// Contextual backgrounds -// For now we'll leave these alongside the text classes until v4 when we can -// safely shift things around (per SemVer rules). -.bg-primary { - // Given the contrast here, this is the only class to have its color inverted - // automatically. - color: #fff; -} -@include bg-variant('.bg-primary', $brand-primary); - -@include bg-variant('.bg-success', $state-success-bg); - -@include bg-variant('.bg-info', $state-info-bg); - -@include bg-variant('.bg-warning', $state-warning-bg); - -@include bg-variant('.bg-danger', $state-danger-bg); - - -// Page header -// ------------------------- - -.page-header { - padding-bottom: (($line-height-computed / 2) - 1); - margin: ($line-height-computed * 2) 0 $line-height-computed; - border-bottom: 1px solid $page-header-border-color; -} - - -// Lists -// ------------------------- - -// Unordered and Ordered lists -ul, -ol { - margin-top: 0; - margin-bottom: ($line-height-computed / 2); - ul, - ol { - margin-bottom: 0; - } -} - -// List options - -// [converter] extracted from `.lm-list-unstyled` for libsass compatibility -@mixin lm-list-unstyled { - padding-left: 0; - list-style: none; -} -// [converter] extracted as `@mixin lm-list-unstyled` for libsass compatibility -.lm-list-unstyled { - @include lm-list-unstyled; -} - - -// Inline turns list items into inline-block -.list-inline { - @include lm-list-unstyled; - margin-left: -5px; - - > li { - display: inline-block; - padding-left: 5px; - padding-right: 5px; - } -} - -// Description Lists -dl { - margin-top: 0; // Remove browser default - margin-bottom: $line-height-computed; -} -dt, -dd { - line-height: $line-height-base; -} -dt { - font-weight: bold; -} -dd { - margin-left: 0; // Undo browser default -} - -// Horizontal description lists -// -// Defaults to being stacked without any of the below styles applied, until the -// grid breakpoint is reached (default of ~768px). - -.dl-horizontal { - dd { - @include clearfix; // Clear the floated `dt` if an empty `dd` is present - } - - @media (min-width: $dl-horizontal-breakpoint) { - dt { - float: left; - width: ($dl-horizontal-offset - 20); - clear: left; - text-align: right; - @include text-overflow; - } - dd { - margin-left: $dl-horizontal-offset; - } - } -} - - -// Misc -// ------------------------- - -// Abbreviations and acronyms -abbr[title], -// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257 -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted $abbr-border-color; -} -.initialism { - font-size: 90%; - @extend .text-uppercase; -} - -// Blockquotes -blockquote { - padding: ($line-height-computed / 2) $line-height-computed; - margin: 0 0 $line-height-computed; - font-size: $blockquote-font-size; - border-left: 5px solid $blockquote-border-color; - - p, - ul, - ol { - &:last-child { - margin-bottom: 0; - } - } - - // Note: Deprecated small and .small as of v3.1.0 - // Context: https://github.com/twbs/bootstrap/issues/11660 - footer, - small, - .small { - display: block; - font-size: 80%; // back to default font-size - line-height: $line-height-base; - color: $blockquote-small-color; - - &:before { - content: '\2014 \00A0'; // em dash, nbsp - } - } -} - -// Opposite alignment of blockquote -// -// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0. -.blockquote-reverse, -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - border-right: 5px solid $blockquote-border-color; - border-left: 0; - text-align: right; - - // Account for citation - footer, - small, - .small { - &:before { content: ''; } - &:after { - content: '\00A0 \2014'; // nbsp, em dash - } - } -} - -// Addresses -address { - margin-bottom: $line-height-computed; - font-style: normal; - line-height: $line-height-base; -} \ No newline at end of file diff --git a/src/mol-app/skin/bootstrap/variables.scss b/src/mol-app/skin/bootstrap/variables.scss deleted file mode 100644 index ead0db3c4d7894471005eef2ce9f105ae82fa1b3..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/bootstrap/variables.scss +++ /dev/null @@ -1,353 +0,0 @@ -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -$gray-base: #000 !default; -$gray-darker: lighten($gray-base, 13.5%) !default; // #222 -$gray-dark: lighten($gray-base, 20%) !default; // #333 -$gray: lighten($gray-base, 33.5%) !default; // #555 -$gray-light: lighten($gray-base, 46.7%) !default; // #777 -$gray-lighter: lighten($gray-base, 93.5%) !default; // #eee - -$brand-primary: darken(#428bca, 6.5%) !default; // #337ab7 -$brand-success: #5cb85c !default; -$brand-info: #5bc0de !default; -$brand-warning: #f0ad4e !default; -$brand-danger: #d9534f !default; - - -//== Scaffolding -// -//## Settings for some of the most global styles. - -//** Background color for `<body>`. -$body-bg: #fff !default; -//** Global text color on `<body>`. -$text-color: $gray-dark !default; - -//** Global textual link color. -$link-color: $brand-primary !default; -//** Link hover color set via `darken()` function. -$link-hover-color: darken($link-color, 15%) !default; -//** Link hover decoration. -$link-hover-decoration: underline !default; - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif !default; -$font-family-serif: Georgia, "Times New Roman", Times, serif !default; -//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`. -$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace !default; -$font-family-base: $font-family-sans-serif !default; - -$font-size-base: 14px !default; -$font-size-large: ceil(($font-size-base * 1.25)) !default; // ~18px -$font-size-small: ceil(($font-size-base * 0.85)) !default; // ~12px - -$font-size-h1: floor(($font-size-base * 2.6)) !default; // ~36px -$font-size-h2: floor(($font-size-base * 2.15)) !default; // ~30px -$font-size-h3: ceil(($font-size-base * 1.7)) !default; // ~24px -$font-size-h4: ceil(($font-size-base * 1.25)) !default; // ~18px -$font-size-h5: $font-size-base !default; -$font-size-h6: ceil(($font-size-base * 0.85)) !default; // ~12px - -//** Unit-less `line-height` for use in components like buttons. -$line-height-base: 1.428571429 !default; // 20/14 -//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc. -$line-height-computed: floor(($font-size-base * $line-height-base)) !default; // ~20px - -//** By default, this inherits from the `<body>`. -$headings-font-family: inherit !default; -$headings-font-weight: 500 !default; -$headings-line-height: 1.1 !default; -$headings-color: inherit !default; - - -//== Components -// -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). - -$padding-base-vertical: 6px !default; -$padding-base-horizontal: 12px !default; - -$padding-large-vertical: 10px !default; -$padding-large-horizontal: 16px !default; - -$padding-small-vertical: 5px !default; -$padding-small-horizontal: 10px !default; - -$padding-xs-vertical: 1px !default; -$padding-xs-horizontal: 5px !default; - -$line-height-large: 1.3333333 !default; // extra decimals for Win 8.1 Chrome -$line-height-small: 1.5 !default; - -$border-radius-base: 4px !default; -$border-radius-large: 6px !default; -$border-radius-small: 3px !default; - -//** Global color for active items (e.g., navs or dropdowns). -$component-active-color: #fff !default; -//** Global background color for active items (e.g., navs or dropdowns). -$component-active-bg: $brand-primary !default; - -//** Width of the `border` for generating carets that indicator dropdowns. -$caret-width-base: 4px !default; -//** Carets increase slightly in size for larger components. -$caret-width-large: 5px !default; - - -//== Buttons -// -//## For each of Bootstrap's buttons, define text, background and border color. - -$molstar-btn-font-weight: normal !default; - -$molstar-btn-default-color: #333 !default; -$molstar-btn-default-bg: #fff !default; -$molstar-btn-default-border: #ccc !default; - -$molstar-btn-primary-color: #fff !default; -$molstar-btn-primary-bg: $brand-primary !default; -$molstar-btn-primary-border: darken($molstar-btn-primary-bg, 5%) !default; - -$molstar-btn-success-color: #fff !default; -$molstar-btn-success-bg: $brand-success !default; -$molstar-btn-success-border: darken($molstar-btn-success-bg, 5%) !default; - -$molstar-btn-info-color: #fff !default; -$molstar-btn-info-bg: $brand-info !default; -$molstar-btn-info-border: darken($molstar-btn-info-bg, 5%) !default; - -$molstar-btn-warning-color: #fff !default; -$molstar-btn-warning-bg: $brand-warning !default; -$molstar-btn-warning-border: darken($molstar-btn-warning-bg, 5%) !default; - -$molstar-btn-danger-color: #fff !default; -$molstar-btn-danger-bg: $brand-danger !default; -$molstar-btn-danger-border: darken($molstar-btn-danger-bg, 5%) !default; - -$molstar-btn-link-disabled-color: $gray-light !default; - -// Allows for customizing button radius independently from global border radius -$molstar-btn-border-radius-base: $border-radius-base !default; -$molstar-btn-border-radius-large: $border-radius-large !default; -$molstar-btn-border-radius-small: $border-radius-small !default; - - -//== Media queries breakpoints -// -//## Define the breakpoints at which your layout will change, adapting to different screen sizes. - -// Extra small screen / phone -//** Deprecated `$screen-xs` as of v3.0.1 -$screen-xs: 480px !default; -//** Deprecated `$screen-xs-min` as of v3.2.0 -$screen-xs-min: $screen-xs !default; -//** Deprecated `$screen-phone` as of v3.0.1 -$screen-phone: $screen-xs-min !default; - -// Small screen / tablet -//** Deprecated `$screen-sm` as of v3.0.1 -$screen-sm: 768px !default; -$screen-sm-min: $screen-sm !default; -//** Deprecated `$screen-tablet` as of v3.0.1 -$screen-tablet: $screen-sm-min !default; - -// Medium screen / desktop -//** Deprecated `$screen-md` as of v3.0.1 -$screen-md: 992px !default; -$screen-md-min: $screen-md !default; -//** Deprecated `$screen-desktop` as of v3.0.1 -$screen-desktop: $screen-md-min !default; - -// Large screen / wide desktop -//** Deprecated `$screen-lg` as of v3.0.1 -$screen-lg: 1200px !default; -$screen-lg-min: $screen-lg !default; -//** Deprecated `$screen-lg-desktop` as of v3.0.1 -$screen-lg-desktop: $screen-lg-min !default; - -// So media queries don't overlap when required, provide a maximum -$screen-xs-max: ($screen-sm-min - 1) !default; -$screen-sm-max: ($screen-md-min - 1) !default; -$screen-md-max: ($screen-lg-min - 1) !default; - - -//== Grid system -// -//## Define your custom responsive grid. - -//** Number of columns in the grid. -$grid-columns: 12 !default; -//** Padding between columns. Gets divided in half for the left and right. -$grid-gutter-width: 30px !default; -// Navbar collapse -//** Point at which the navbar becomes uncollapsed. -$grid-float-breakpoint: $screen-sm-min !default; -//** Point at which the navbar begins collapsing. -$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default; - - -//== Forms -// -//## - -//** `<input>` background color -$input-bg: #fff !default; -//** `<input disabled>` background color -$input-bg-disabled: $gray-lighter !default; - -//** Text color for `<input>`s -$input-color: $gray !default; -//** `<input>` border color -$input-border: #ccc !default; - -// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4 -//** Default `.lm-form-control` border radius -// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS. -$input-border-radius: $border-radius-base !default; -//** Large `.lm-form-control` border radius -$input-border-radius-large: $border-radius-large !default; -//** Small `.lm-form-control` border radius -$input-border-radius-small: $border-radius-small !default; - -//** Border color for inputs on focus -$input-border-focus: #66afe9 !default; - -//** Placeholder text color -$input-color-placeholder: #999 !default; - -//** Default `.lm-form-control` height -$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) !default; -//** Large `.lm-form-control` height -$input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default; -//** Small `.lm-form-control` height -$input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default; - -//** `.form-group` margin -$form-group-margin-bottom: 15px !default; - -$legend-color: $gray-dark !default; -$legend-border-color: #e5e5e5 !default; - -//** Background color for textual input addons -$input-group-addon-bg: $gray-lighter !default; -//** Border color for textual input addons -$input-group-addon-border-color: $input-border !default; - -//** Disabled cursor for form controls and buttons. -$cursor-disabled: not-allowed !default; - - -//== Thumbnails -// -//## - -//** Padding around the thumbnail image -$thumbnail-padding: 4px !default; -//** Thumbnail background color -$thumbnail-bg: $body-bg !default; -//** Thumbnail border color -$thumbnail-border: #ddd !default; -//** Thumbnail border radius -$thumbnail-border-radius: $border-radius-base !default; - -//** Custom text color for thumbnail captions -$thumbnail-caption-color: $text-color !default; -//** Padding around the thumbnail caption -$thumbnail-caption-padding: 9px !default; - - -//== Type -// -//## - -//** Horizontal offset for forms and lists. -$component-offset-horizontal: 180px !default; -//** Text muted color -$text-muted: $gray-light !default; -//** Abbreviations and acronyms border color -$abbr-border-color: $gray-light !default; -//** Headings small color -$headings-small-color: $gray-light !default; -//** Blockquote small color -$blockquote-small-color: $gray-light !default; -//** Blockquote font size -$blockquote-font-size: ($font-size-base * 1.25) !default; -//** Blockquote border color -$blockquote-border-color: $gray-lighter !default; -//** Page header border color -$page-header-border-color: $gray-lighter !default; -//** Width of horizontal description list titles -$dl-horizontal-offset: $component-offset-horizontal !default; -//** Point at which .dl-horizontal becomes horizontal -$dl-horizontal-breakpoint: $grid-float-breakpoint !default; -//** Horizontal line color. -$hr-border: $gray-lighter !default; - - -//== Form states and alerts -// -//## Define colors for form feedback states and, by default, alerts. - -$state-success-text: #3c763d !default; -$state-success-bg: #dff0d8 !default; -$state-success-border: darken(adjust-hue($state-success-bg, -10), 5%) !default; - -$state-info-text: #31708f !default; -$state-info-bg: #d9edf7 !default; -$state-info-border: darken(adjust-hue($state-info-bg, -10), 7%) !default; - -$state-warning-text: #8a6d3b !default; -$state-warning-bg: #fcf8e3 !default; -$state-warning-border: darken(adjust-hue($state-warning-bg, -10), 5%) !default; - -$state-danger-text: #a94442 !default; -$state-danger-bg: #f2dede !default; -$state-danger-border: darken(adjust-hue($state-danger-bg, -10), 5%) !default; - - -//== Labels -// -//## - -//** Default label background color -$label-default-bg: $gray-light !default; -//** Primary label background color -$label-primary-bg: $brand-primary !default; -//** Success label background color -$label-success-bg: $brand-success !default; -//** Info label background color -$label-info-bg: $brand-info !default; -//** Warning label background color -$label-warning-bg: $brand-warning !default; -//** Danger label background color -$label-danger-bg: $brand-danger !default; - -//** Default label text color -$label-color: #fff !default; -//** Default text color of a linked label -$label-link-hover-color: #fff !default; - - -//== Badges -// -//## - -$badge-color: #fff !default; -//** Linked badge text color on hover -$badge-link-hover-color: #fff !default; -$badge-bg: $gray-light !default; - -//** Badge text color in active nav link -$badge-active-color: $link-color !default; -//** Badge background color in active nav link -$badge-active-bg: #fff !default; - -$badge-font-weight: bold !default; -$badge-line-height: 1 !default; -$badge-border-radius: 10px !default; \ No newline at end of file diff --git a/src/mol-app/skin/colors/blue.scss b/src/mol-app/skin/colors/blue.scss deleted file mode 100644 index c31a02bd7acd89bebce6bb407ade29934725f3e5..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/colors/blue.scss +++ /dev/null @@ -1,24 +0,0 @@ -$default-background: #2D3E50; -$font-color: #EDF1F2; -$hover-font-color: #3B9AD9; -$entity-current-font-color: #FFFFFF; -$lm-btn-remove-background: #BF3A31; -$lm-btn-remove-hover-font-color:#ffffff; -$lm-btn-commit-on-font-color: #ffffff; -$entity-badge-font-color: #ccd4e0; - -// used in LOG -$log-message: #0CCA5D; -$log-info: #5E3673; -$log-warning: #FCC937; -$log-error: #FD354B; - -$logo-background: rgba(0,0,0,0.75); - -@function color-lower-contrast($color, $amount) { - @return darken($color, $amount); -} - -@function color-increase-contrast($color, $amount) { - @return lighten($color, $amount); -} \ No newline at end of file diff --git a/src/mol-app/skin/colors/dark.scss b/src/mol-app/skin/colors/dark.scss deleted file mode 100644 index 6df758473092906b8ceeb171213a18daec8330af..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/colors/dark.scss +++ /dev/null @@ -1,22 +0,0 @@ -$default-background: #111318; -$font-color: #ccd4e0; -$hover-font-color: #51A2FB; -$entity-current-font-color: #68BEFD; -$molstar-btn-remove-background: #DE0A28; -$molstar-btn-remove-hover-font-color:#F2F4F7; -$molstar-btn-commit-on-font-color: #68BEFD; -$entity-badge-font-color: #ccd4e0; - -// used in LOG -$log-message: #0CCA5D; -$log-info: #5E3673; -$log-warning: #FCC937; -$log-error: #FD354B; - -@function color-lower-contrast($color, $amount) { - @return darken($color, $amount); -} - -@function color-increase-contrast($color, $amount) { - @return lighten($color, $amount); -} \ No newline at end of file diff --git a/src/mol-app/skin/colors/light.scss b/src/mol-app/skin/colors/light.scss deleted file mode 100644 index 678b744d5ba2a392d60a23262e955e7f1d28bbc9..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/colors/light.scss +++ /dev/null @@ -1,30 +0,0 @@ -// this is complement of the dark theme - -@function compl($color) { - @return rgb(255 - red($color), 255 - green($color), 255 - blue($color)); -} - -$default-background: compl(#111318); -$font-color: compl(#ccd4e0); -$hover-font-color: compl(#51A2FB); -$entity-current-font-color: compl(#68BEFD); -$molstar-btn-commit-on-font-color: compl(#68BEFD); -$entity-badge-font-color: lighten(#ccd4e0,10%); -$molstar-btn-remove-background: #DE0A28; -$molstar-btn-remove-hover-font-color:#F2F4F7; - -// used in LOG -$log-message: #0CCA5D; -$log-info: #5E3673; -$log-warning: #FCC937; -$log-error: #FD354B; - -$logo-background: rgba(204,201,193,0.85); - -@function color-lower-contrast($color, $amount) { - @return lighten($color, $amount); -} - -@function color-increase-contrast($color, $amount) { - @return darken($color, $amount); -} \ No newline at end of file diff --git a/src/mol-app/skin/components/controls-base.scss b/src/mol-app/skin/components/controls-base.scss deleted file mode 100644 index e1f17a6837df972004d8b8feb8a88383884950b2..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/controls-base.scss +++ /dev/null @@ -1,144 +0,0 @@ -.molstar-btn { - padding: 0 $control-spacing; - line-height: $row-height; - border: none; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.molstar-btn, .molstar-btn:active, .molstar-btn-link:focus, .molstar-btn:hover { - outline: none !important; -} - -.molstar-btn-icon { - height: $row-height; - width: $row-height; - line-height: $row-height; - padding: 0; - text-align: center; -} - -.molstar-btn-link { - .molstar-icon { - font-size: 100%; - } -} - -.molstar-btn-link, .molstar-btn-link:active, .molstar-btn-link:focus { - color: $molstar-btn-link-font-color; - text-decoration: none; -} - -.molstar-btn-link:hover { - color: $hover-font-color; - text-decoration: none; -} - -.molstar-btn-link-toggle-on { - color: $molstar-btn-link-toggle-on-font-color; -} - -.molstar-btn-link-toggle-off, .molstar-btn-link-toggle-off:active, .molstar-btn-link-toggle-off:focus { - color: $molstar-btn-link-toggle-off-font-color; -} - -.molstar-btn-link-toggle-off:hover, .molstar-btn-link-toggle-on:hover { - color: $hover-font-color; -} - -@mixin molstar-btn($name, $font, $bg) { - .molstar-btn-#{$name}, .molstar-btn-#{$name}:active, .molstar-btn-#{$name}:focus { - color: $font; - background: $bg; - } - .molstar-btn-#{$name}:hover { - color: $hover-font-color; - background: color-lower-contrast($bg, 2.5%); - } - - .molstar-btn-#{$name}[disabled], .molstar-btn-#{$name}[disabled]:hover, - .molstar-btn-#{$name}[disabled]:active, .molstar-btn-#{$name}[disabled]:focus { - color: color-lower-contrast($font, 1%); - } -} - -@include molstar-btn('remove', $molstar-btn-remove-font-color, $molstar-btn-remove-background); -@include molstar-btn('action', $font-color, $molstar-btn-action-background); -@include molstar-btn('commit-on', $molstar-btn-commit-on-font-color, $molstar-btn-commit-on-background); -@include molstar-btn('commit-off', $molstar-btn-commit-off-font-color, $molstar-btn-commit-off-background); - -.molstar-btn-remove:hover { - color: $molstar-btn-remove-hover-font-color; -} -.molstar-btn-commit-on:hover { - color: $molstar-btn-commit-on-hover-font-color; -} - -.molstar-btn-action { - height: $row-height; - line-height: $row-height; -} - -.molstar-form-control { - width: 100%; - background: $molstar-form-control-background; - color: $font-color; - border: none !important; - padding: 0 $control-spacing; - line-height: $row-height - 2px; - height: $row-height; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - box-shadow: none !important; - - &:hover { - color: $hover-font-color; - background-color: color-increase-contrast($molstar-form-control-background, 5%); - border: none; - outline-offset: -1px; - outline: 1px solid color-increase-contrast($molstar-form-control-background, 20%); - } - - &:active, &:focus { - color: $font-color; - background-color: $molstar-form-control-background; - border: none; - outline-offset: 0; - outline: none; - } -} - -.molstar-btn-commit { - text-align: right; - padding-top: 0; - padding-bottom: 0; - padding-right: $control-spacing; - padding-left: 0; - line-height: $row-height; - border: none; - overflow: hidden; - - .molstar-icon { - display: block-inline; - line-height: $row-height; - margin-right: $control-spacing; - width: $row-height; - text-align: center; - float: left; - } -} - -select.molstar-form-control { - background: none; - background-color: $molstar-form-control-background; - background-size: 8px 12px; - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAUCAMAAACzvE1FAAAADFBMVEUzMzMzMzMzMzMzMzMKAG/3AAAAA3RSTlMAf4C/aSLHAAAAPElEQVR42q3NMQ4AIAgEQTn//2cLdRKppSGzBYwzVXvznNWs8C58CiussPJj8h6NwgorrKRdTvuV9v16Afn0AYFOB7aYAAAAAElFTkSuQmCC); - background-repeat: no-repeat; - background-position: right $control-spacing top (($row-height - 12px) / 2); -} - -select.molstar-form-control:-moz-focusring { - color: transparent; - text-shadow: 0 0 0 $font-color; -} \ No newline at end of file diff --git a/src/mol-app/skin/components/controls.scss b/src/mol-app/skin/components/controls.scss deleted file mode 100644 index 2c8aeda0a62cc83464d9dfc128dcf5a1e7f4f1aa..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/controls.scss +++ /dev/null @@ -1,197 +0,0 @@ - -.molstar-control-row { - position: relative; - height: $row-height; - background: $default-background; - margin-top: 1px; - - > span { - line-height: $row-height; - display: block; - width: $control-label-width + $control-spacing; - text-align: right; - padding: 0 $control-spacing; - color: color-lower-contrast($font-color, 15%); - - @include non-selectable; - } - - select, button, input[type=text] { - @extend .molstar-form-control; - } - - button { - @extend .molstar-btn; - @extend .molstar-btn-block; - } - - > div:nth-child(2) { - background: $molstar-form-control-background; - position: absolute; - left: $control-label-width + $control-spacing; - top: 0; - right: 0; - bottom: 0; - } -} - -.molstar-control-group { - position: relative; -} - -.molstar-toggle-button { - .molstar-icon { - display: inline-block; - margin-right: 6px; - } - - > div > button:hover { - border-color: color-increase-contrast($molstar-form-control-background, 5%) !important; - border: none; - outline-offset: -1px !important; - outline: 1px solid color-increase-contrast($molstar-form-control-background, 20%) !important; - } -} - -.molstar-slider { - > div { - > div:first-child { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - width: 100%; - padding-right: 50px; - display: table; - - > div { - height: $row-height; - display: table-cell; - vertical-align: middle; - padding: 0 ($control-spacing + 4px); - } - } - > div:last-child { - position: absolute; - height: $row-height; - right: 0; - width: 50px; - top: 0; - bottom: 0; - } - } - - input[type=text] { - text-align: right; - } - - input[type=range] { - width: 100%; - } -} - -.molstar-toggle-color-picker { - button { - border: $control-spacing solid $molstar-form-control-background !important; - margin: 0; - text-align: center; - padding-right: $control-spacing; - padding-left: $control-spacing; - - &:hover { - border-color: color-increase-contrast($molstar-form-control-background, 5%) !important; - border: none; - outline-offset: -1px !important; - outline: 1px solid color-increase-contrast($molstar-form-control-background, 20%) !important; - } - } - - .molstar-color-picker { - position: absolute; - z-index: 100000; - background: $default-background; - border-top: 1px solid $default-background; - padding-bottom: $control-spacing / 2; - width: 100%; - - // input[type=text] { - // background: $molstar-form-control-background !important; - // } - } -} - -.molstar-toggle-color-picker-above { - .molstar-color-picker { - top: -2 * 32px - 16px - $control-spacing / 2; - height: 2 * 32px + 16px + $control-spacing / 2; - } -} - -.molstar-toggle-color-picker-below { - .molstar-color-picker { - top: $row-height; - height: 2 * 32px + 16px; - } -} - - -.molstar-control-subgroup { - margin-top: 1px; - - .molstar-control-row { - margin-left: $control-spacing !important; - > span { - width: $control-label-width !important; - } - - > div:nth-child(2) { - left: $control-label-width !important; - } - } -} - -.molstar-conrol-group-expander { - display: block; - position: absolute; - line-height: $row-height; - padding: 0; - left: 0; - top: 0; - width: $control-label-width + $control-spacing; - text-align: left; - - .molstar-icon { - line-height: $row-height - 3; - width: $row-height - 1; - text-align: center; - display: inline-block; - font-size: 100%; - } -} - -.molstar-plugin-layout_controls { - position: absolute; - left: $control-spacing; - top: $control-spacing; -} - -.molstar-plugin-layout_controls > button:first-child { - margin-right: 6px; -} - -.molstar-empty-control { - display: none; -} - -.molstar-control .molstar-btn-block { - margin-bottom: 0px; - margin-top: 0px; -} - -.molstar-row-text { - > div { - line-height: $row-height; - text-align: center; - } -} \ No newline at end of file diff --git a/src/mol-app/skin/components/entity.scss b/src/mol-app/skin/components/entity.scss deleted file mode 100644 index 3ce2e2305532c1d2a498233331d422ad45467acf..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/entity.scss +++ /dev/null @@ -1,225 +0,0 @@ - - -.molstar-entity-tree { - overflow: hidden; - position: absolute; - bottom: 0; - left: 0; - right: 0; - top: 0; - padding-top: $control-spacing; - background: $control-background; - - .molstar-entity-tree-children { - overflow-x: hidden; - overflow-y: auto; - position: absolute; - bottom: 0; - left: 0; - right: 0; - top: $row-height + $control-spacing + 1; - padding: $control-spacing 0; - } -} - -.molstar-entity-store-header { - height: $row-height + 1; - position: relative; - - > span { - margin-left: 6px; - display: inline-block; - line-height: $row-height; - font-weight: bold; - - @include non-selectable - } - - button { - display: block !important; - height: $row-height !important; - margin: 0 !important; - line-height: $row-height !important; - border: none !important; - position: absolute; - top: 0; - } - - border-bottom: 1px solid $border-color; -} - -.molstar-entity-store-root { - overflow-x: hidden; - overflow-y: auto; - position: absolute; - bottom: 0; - left: 0; - top: $row-height + 1; - right: 0; -} - -.molstar-entity-tree-entry { - height: $row-height + 1; - position: relative; - border-bottom: 1px solid $control-background; -} - -.molstar-entity-tree-entry-current { - background: color-lower-contrast($default-background, 4%) !important; - - .molstar-entity-tree-entry-label { - color: $entity-current-font-color; - font-weight: bold; - .molstar-entity-tree-entry-label-tag { - font-weight: normal; - } - &:hover { - color: $hover-font-color; - } - } -} - -.molstar-entity-tree-entry-current-path { - background: color-lower-contrast($default-background, 2%) !important; - .molstar-entity-tree-entry-label { - color: color-lower-contrast($entity-current-font-color, 5%); - &:hover { - color: $hover-font-color; - } - } -} - -.molstar-entity-tree-entry button, .molstar-entity-tree-entry > div { - display: block !important; - height: $row-height !important; - margin: 0 !important; - line-height: $row-height !important; - border: none !important; - position: absolute; - top: 0; -} - - -.molstar-entity-tree-entry-toggle-group { - width: $row-height; - height: $row-height; - padding: 0; - left: 0; -} - -.molstar-entity-tree-entry-toggle-visible { - width: $row-height; - right: 0; //$row-height + 6; - padding: 0 !important; - font-size: 80%; -} - -.molstar-entity-tree-entry-toggle-visible-full, .molstar-entity-tree-entry-toggle-visible-full:focus, .molstar-entity-tree-entry-toggle-visible-full:active { - color: $entity-color-fully-visible; -} - -.molstar-entity-tree-entry-toggle-visible-partial, .molstar-entity-tree-entry-toggle-visible-partial:focus, .molstar-entity-tree-entry-toggle-visible-partial:active { - color: $entity-color-partialy-visible; -} - -.molstar-entity-tree-entry-toggle-visible-none, .molstar-entity-tree-entry-toggle-visible-none:focus, .molstar-entity-tree-entry-toggle-visible-none:active { - //background: transparent !important; - color: $entity-color-not-visible; -} - -.molstar-entity-tree-entry-remove { - width: $row-height; - height: $row-height; - right: $row-height; - padding: 0 !important; - text-align: center; - font-size: 80%; - color: color-lower-contrast($font-color, 66%) -} - -.molstar-entity-tree-entry-body { - position: absolute; - left: $row-height; - border-radius: 0 0 0 $entity-subtree-offset; - right: 0; - background: $default-background; -} - -.molstar-entity-tree-entry .molstar-entity-badge { - width: $row-height; - position: absolute; - height: $row-height; - left: 0; - top: 0; - border-radius: 0 $entity-subtree-offset 0 $entity-subtree-offset; -} - -.molstar-entity-tree-entry-label-wrap { - right: 2 * $row-height; - overflow: hidden; - left: $row-height; - height: $row-height; - position: absolute; -} - -.molstar-entity-tree-entry-label { - position: absolute; - right: 0; - top: 0; - left: 0; - text-align: left !important; - width: 100%; - padding: 0 $control-spacing !important; -} - -.molstar-entity-tree-entry-label-tag { - color: $entity-tag-color; - font-size: 70%; - display: inline-block; - margin-left: 6px; -} - - -.molstar-entity-tree-children-wrap { - padding-left: $entity-subtree-offset; -} - -.molstar-entity-tree-root { - > .molstar-entity-tree-entry { - .molstar-entity-badge { - border-top-right-radius: 0; - } - .molstar-entity-tree-entry-label { - font-weight: bold; - } - .molstar-entity-tree-entry-toggle-group { - display: none !important; - } - .molstar-entity-tree-entry-body { - left: $row-height - $entity-subtree-offset !important; - } - background: $default-background; - border-bottom: 1px solid $border-color; - } - - > .molstar-entity-tree-children-wrap { - margin-top: $control-spacing; - padding-left: 0 !important; - } -} - -.molstar-panel { - .molstar-entity-tree-entry-toggle-visible { - position: absolute; - top: 0; - right: 0; - height: $row-height; - font-size: 100%; - - background: $default-background; //color-increase-contrast($default-background, 4%); - } - - // .molstar-entity-tree-entry-toggle-visible-full { - // background: color-increase-contrast($default-background, 8%); - // } -} \ No newline at end of file diff --git a/src/mol-app/skin/components/help.scss b/src/mol-app/skin/components/help.scss deleted file mode 100644 index 31b400458ef9f0adc6c6792e39e61297b1f904e0..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/help.scss +++ /dev/null @@ -1,28 +0,0 @@ - -.molstar-help-row { - position: relative; - height: $row-height; - background: $default-background; - margin-top: 1px; - display: table; - width: 100%; - - > span { - width: $control-label-width + $control-spacing; - text-align: right; - padding: $info-vertical-padding $control-spacing; - color: color-lower-contrast($font-color, 15%); - display: table-cell; - font-weight: bold; - - @include non-selectable; - } - - > div { - background: $molstar-form-control-background; - position: relative; - padding: $info-vertical-padding $control-spacing; - display: table-cell; - color: color-lower-contrast($font-color, 15%); - } -} \ No newline at end of file diff --git a/src/mol-app/skin/components/jobs.scss b/src/mol-app/skin/components/jobs.scss deleted file mode 100644 index 13bae9ef1cc2d685ba76a4e393f2163b0979fd15..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/jobs.scss +++ /dev/null @@ -1,131 +0,0 @@ -.molstar-job-state { - - line-height: $row-height; - //height: $row-height; - //position: relative; - //margin-top: 1px; - - > span { - @include non-selectable; - //display: inline-block; - //padding: 0 $control-spacing; - } - - // > button { - // margin-top: -2px; - // float: left; - // display: block; - // line-height: $row-height; - // height: $row-height; - // } -} - -/* overlay */ - -.molstar-overlay { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - z-index: 1000; - - .molstar-overlay-background { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: transparent; - //background: black; - //opacity: 0.5; - } - - .molstar-overlay-content-wrap { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - display: block; - width: 100%; - height: 100%; - } - - .molstar-overlay-content { - text-align: center; - - > div { - - padding-top: 2 * $row-height; - - .molstar-job-state { - $size: $row-height; - text-align: center; - - > div { - height: $size; - margin-top: $control-spacing; - position: relative; - text-align: center; - width: 100%; - - > div { - height: $size; - line-height: $size; - display: inline-block; - background: $default-background; - padding: 0 ($control-spacing); - font-weight: bold; - @include non-selectable; - } - - > button { - display: inline-block; - margin-top: -3px; - font-size: 140%; - } - } - } - } - } -} - -/* background */ - -.molstar-background-jobs { - position: absolute; - left: 0; - bottom: 0; - z-index: 1000; - - .molstar-job-state { - $size: $row-height; - - > div { - height: $size; - margin-top: 1px; - position: relative; - width: 100%; - background: $default-background; - - > div { - height: $size; - line-height: $size; - display: inline-block; - padding: 0 ($control-spacing); - @include non-selectable; - } - - > button { - display: inline-block; - margin-top: -3px; - font-size: 140%; - } - } - } -} - -// .molstar-background-jobs .molstar-job-state { -// color: -// } diff --git a/src/mol-app/skin/components/log.scss b/src/mol-app/skin/components/log.scss deleted file mode 100644 index 9bc74918c8a11a2958d0843fecf2908d7f3201cd..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/log.scss +++ /dev/null @@ -1,97 +0,0 @@ - -.molstar-log-wrap { - position: absolute; - right: 0; - top: 0; - left: 0; - bottom: 0; - overflow: hidden; -} - -.molstar-log { - position: absolute; - right: -20px; - top: 0; - left: 0; - bottom: 0; - overflow-y: scroll; - overflow-x: hidden; - font-size: 90%; - background: $control-background; -} - -.molstar-log { - ul { - padding: 0; - margin: 0; - } - - color: $log-font-color; - - li { - clear: both; - margin: 0; - background: $default-background; - position: relative; - - &:not(:last-child) { - border-bottom: 1px solid $border-color; - } - } - - - .molstar-log-entry { - margin-left: $control-label-width; - background: color-lower-contrast($control-background, 5%); - padding: $info-vertical-padding ($control-spacing + 15px) $info-vertical-padding $control-spacing ; - } - - .molstar-log-timestamp { - padding: ($info-vertical-padding + 1) $control-spacing ($info-vertical-padding - 1) $control-spacing; - float: left; - text-align: right; - width: $control-label-width; - color: $log-timestamp-font-color; - //vertical-align: baseline; - //line-height: $row-height; - font-size: 90%; - } - - .molstar-log-timestamp small { - font-size: 90%; - } -} - -// .molstar-log hr { -// border-color: $separator-color; -// margin: 3px 3px 0 5px; -// } - -.molstar-log .label { - margin-top: -3px; - font-size: 7pt; -} - -.molstar-log-entry-badge { - position: absolute; - left: 0; - top: 0; - bottom: 0; - width: 6px; -} - -.molstar-log-entry-message { - background: $log-message; -} - -.molstar-log-entry-info { - background: $log-info; -} - -.molstar-log-entry-error { - background: $log-error; -} - -.molstar-log-entry-warning { - background: $log-warning; -} diff --git a/src/mol-app/skin/components/misc.scss b/src/mol-app/skin/components/misc.scss deleted file mode 100644 index a19eefd6ad19ccdcadb3c01f71345274e5ef74e5..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/misc.scss +++ /dev/null @@ -1,69 +0,0 @@ -.molstar-description { - padding: $control-spacing; - font-size: 85%; - background: $default-background; - text-align: center; - //font-style: italic; - - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+ */ - - /* Rules below not implemented in browsers yet */ - -o-user-select: none; - user-select: none; - - font-weight: light; - - cursor: default; -} - -.molstar-description:not(:first-child) { - border-top: 1px solid $control-background; -} - -.molstar-color-picker input { - color: black !important; -} - -.molstar-no-webgl { - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - display: table; - text-align: center; - - > div { - b { - font-size: 120%; - } - display: table-cell; - vertical-align: middle; - text-align: center; - width: 100%; - height: 100%; - } -} - -.molstar-loader-molstar-btn-file { - position: relative; - overflow: hidden; -} - -.molstar-loader-molstar-btn-file input[type=file] { - position: absolute; - top: 0; - right: 0; - min-width: 100%; - min-height: 100%; - font-size: 100px; - text-align: right; - filter: alpha(opacity=0); - opacity: 0; - outline: none; - background: white; - cursor: inherit; - display: block; -} \ No newline at end of file diff --git a/src/mol-app/skin/components/panel.scss b/src/mol-app/skin/components/panel.scss deleted file mode 100644 index affbcf9f2c83cf1d952656298871e12d71307563..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/panel.scss +++ /dev/null @@ -1,142 +0,0 @@ -.molstar-panel-header .molstar-panel-expander { - display: block; - width: 100%; - text-align: left; -} - -.molstar-panel-header { - - //border-bottom-width: 1px; - //border-bottom-style: solid; - height: $row-height; - border-color: $border-color; - position: relative; - - //border-radius: $control-spacing 0 0 0; - - .molstar-panel-expander-wrapper { - - position: absolute; - top: 0; - left: 0; - right: 2 * $row-height; - - button { - // width: 100%; - - display: block; - width: 100%; - text-align: left; - - height: $row-height; - line-height: $row-height; - border: none; - font-weight: bold; - //color: $panel-header-font-color; - padding-left: 0; - background: color-lower-contrast($default-background, 4%); - //text-align: right!important; - - .molstar-icon { - display: inline-block; - margin-right: $control-spacing; - width: $row-height; - text-align: center; - } - - &:hover { - background: color-lower-contrast($default-background, 4%); - } - } - } - - .molstar-panel-description-standalone { - > .molstar-icon { - margin-left: $row-height; - } - - width: 2 * $row-height; - } - - .molstar-panel-description-with-action { - width: $row-height; - margin-right: $row-height; - } - - .molstar-panel-description { - color: $font-color; - float: right; - background: color-lower-contrast($default-background, 4%); - //margin-right: $row-height; - - > .molstar-icon { - display: block; - width: $row-height; - height: $row-height; - line-height: $row-height; - text-align: center; - font-size: 70%; - cursor: default; - background: color-lower-contrast($default-background, 4%); - color: color-lower-contrast($font-color, 66%); - } - - .molstar-panel-description-content { - @include non-selectable; - - color: $font-color; - display: none; - position: absolute; - left: 0; - width: 100%; - background: color-increase-contrast($molstar-form-control-background, 20%); - min-height: $row-height; - z-index: 1000000; - padding: $info-vertical-padding $control-spacing $info-vertical-padding ($row-height + $control-spacing); - text-align: left; - //border-bottom: 1px solid color-lower-contrast($default-background, 4%); - - > .molstar-icon { - position: absolute; - width: $row-height; - height: $row-height; - line-height: $row-height; - text-align: center; - font-size: 80%; - cursor: default; - top: 0; - left: 0; - } - } - - &:hover { - color: $hover-font-color; - > .molstar-icon { - color: $hover-font-color; - } - .molstar-panel-description-content { - display: block; - } - } - } -} - -.molstar-panel-body { - background: $control-background; -} - -.molstar-panel { - margin-bottom: $control-spacing; -} - -.molstar-transform-view { - padding-top: $control-spacing; -} - -.molstar-expandable-group-color-stripe { - position: absolute; - left: 0; - top: $row-height - 2px; - width: $control-label-width + $control-spacing; - height: 2px; -} \ No newline at end of file diff --git a/src/mol-app/skin/components/sequence-view.scss b/src/mol-app/skin/components/sequence-view.scss deleted file mode 100644 index b8bf891675cec72eb8cb18bdd57e5fd6d63a4c7f..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/sequence-view.scss +++ /dev/null @@ -1,9 +0,0 @@ -.molstar-sequence-view-wrap { - position: absolute; - right: 0; - top: 0; - left: 0; - bottom: 0; - overflow: hidden; - overflow-x: scroll; -} \ No newline at end of file diff --git a/src/mol-app/skin/components/slider.scss b/src/mol-app/skin/components/slider.scss deleted file mode 100644 index 2785a3de77b450c00efea05970993147d7083116..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/slider.scss +++ /dev/null @@ -1,164 +0,0 @@ -@mixin borderBox { - box-sizing: border-box; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); // remove tap highlight color for mobile safari - - * { - box-sizing: border-box; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); // remove tap highlight color for mobile safari - } - } - - .molstar-slider-base { - position: relative; - height: 14px; - padding: 5px 0; - width: 100%; - border-radius: $slider-border-radius-base; - @include borderBox; - - &-rail { - position: absolute; - width: 100%; - background-color: $border-color; - height: 4px; - border-radius: 2px; - } - - &-track { - position: absolute; - left: 0; - height: 4px; - border-radius: $slider-border-radius-base; - background-color: tint($font-color, 60%); - } - - &-handle { - position: absolute; - margin-left: -11px; - margin-top: -9px; - width: 22px; - height: 22px; - cursor: pointer; - border-radius: 50%; - background-color: $font-color; - border: 4px solid $border-color; - - &:hover { - background-color: $hover-font-color; - } - } - - &-mark { - position: absolute; - top: 18px; - left: 0; - width: 100%; - font-size: 12px; - } - - &-mark-text { - position: absolute; - display: inline-block; - vertical-align: middle; - text-align: center; - cursor: pointer; - color: #999; - - &-active { - color: #666; - } - } - - &-step { - position: absolute; - width: 100%; - height: 4px; - background: transparent; - } - - &-dot { - position: absolute; - bottom: -2px; - margin-left: -4px; - width: 8px; - height: 8px; - border: 2px solid #e9e9e9; - background-color: #fff; - cursor: pointer; - border-radius: 50%; - vertical-align: middle; - &:first-child { - margin-left: -4px; - } - &:last-child { - margin-left: -4px; - } - &-active { - border-color: tint($font-color, 50%); - } - } - - &-disabled { - background-color: #e9e9e9; - - .molstar-slider-base-track { - background-color: $slider-disabledColor; - } - - .molstar-slider-base-handle, .molstar-slider-base-dot { - border-color: $slider-disabledColor; - background-color: #fff; - cursor: not-allowed; - } - - .molstar-slider-base-mark-text, .molstar-slider-base-dot { - cursor: not-allowed!important; - } - } - } - - .molstar-slider-base-vertical { - width: 14px; - height: 100%; - padding: 0 5px; - - .molstar-slider-base { - &-rail { - height: 100%; - width: 4px; - } - - &-track { - left: 5px; - bottom: 0; - width: 4px; - } - - &-handle { - margin-left: -5px; - margin-bottom: -7px; - } - - &-mark { - top: 0; - left: 18px; - height: 100%; - } - - &-step { - height: 100%; - width: 4px; - } - - &-dot { - left: 2px; - margin-bottom: -4px; - &:first-child { - margin-bottom: -4px; - } - &:last-child { - margin-bottom: -4px; - } - } - } - } \ No newline at end of file diff --git a/src/mol-app/skin/components/viewport.scss b/src/mol-app/skin/components/viewport.scss deleted file mode 100644 index 3ef5c8a6ad5831d446e578e7ddbd4662d945e3c6..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/components/viewport.scss +++ /dev/null @@ -1,93 +0,0 @@ - -.molstar-viewport { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - background: black; - - .molstar-btn-link { - background: rgba(0,0,0,0.2); - } - -} - -.molstar-viewport-expanded { - position: fixed; - z-index: 1000; -} - -.molstar-viewport-container { - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - -webkit-user-select: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-touch-callout: none; -} - -.molstar-viewport-controls { - position: absolute; - right: $control-spacing; - top: $control-spacing; -} - -.molstar-viewport-controls-buttons { - text-align: right; - - > button { - padding: 0; - text-align: center; - width: $row-height; - } - - > button:last-child { - margin-left: $control-spacing; - } - - .molstar-btn-link, .molstar-btn-link-toggle-on { - color: #eee; - } - - .molstar-btn-link-toggle-off { - color: $molstar-btn-link-toggle-off-font-color; - } - - .molstar-btn-link:hover { - color: $hover-font-color; - } -} - -.molstar-viewport-controls-scene-options { - width: 290px; - background: $control-background; -} - -/* highlight */ - -.molstar-highlight-info { - - color: $highlight-info-font-color; - padding: $info-vertical-padding $control-spacing; - background: $default-background; //$highlight-info-background; - - position: absolute; - top: $control-spacing; - left: $control-spacing; - text-align: left; - min-height: $row-height; - max-width: 95%; - - //border-bottom-right-radius: 6px; - z-index: 10000; - @include non-selectable; -} - -.molstar-highlight-info-additional { - font-size: 85%; - display: inline-block; - color: $highlight-info-additional-font-color; -} \ No newline at end of file diff --git a/src/mol-app/skin/fonts/fontello.eot b/src/mol-app/skin/fonts/fontello.eot deleted file mode 100644 index b522411b265bb3854a7f23579001bfe51e4229cb..0000000000000000000000000000000000000000 Binary files a/src/mol-app/skin/fonts/fontello.eot and /dev/null differ diff --git a/src/mol-app/skin/fonts/fontello.svg b/src/mol-app/skin/fonts/fontello.svg deleted file mode 100644 index 753bf788b40774bbb9a88c2b847d0b335975882a..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/fonts/fontello.svg +++ /dev/null @@ -1,442 +0,0 @@ -<?xml version="1.0" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg xmlns="http://www.w3.org/2000/svg"> -<metadata>Copyright (C) 2016 by original authors @ fontello.com</metadata> -<defs> -<font id="fontello" horiz-adv-x="1000" > -<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" /> -<missing-glyph horiz-adv-x="1000" /> -<glyph glyph-name="palette" unicode="" d="M857 622q72-48 101-110t20-104-35-48q-16-4-54 10t-80 10-80-46q-30-46-21-75t34-65 23-50q-2-26-36-63t-126-74-216-37q-186 0-291 101t-95 245q8 118 104 235t216 151q290 84 536-80z m-318-466q30 0 52 22t22 54-22 53-52 21q-32 0-54-21t-22-53 22-54 54-22z" horiz-adv-x="980" /> - -<glyph glyph-name="search" unicode="" d="M772 78q30-34 6-62l-46-46q-36-32-68 0l-190 190q-74-42-156-42-128 0-223 95t-95 223 90 219 218 91 224-95 96-223q0-88-46-162z m-678 358q0-88 68-156t156-68 151 63 63 153q0 88-68 155t-156 67-151-63-63-151z" horiz-adv-x="789" /> - -<glyph glyph-name="flashlight" unicode="" d="M807 706q62-62 85-130t-5-92l-134-134q-16-16-62-26t-96-4l-408-408q-18-18-57-6t-75 50q-36 36-49 74t5 56l408 408q-6 50 4 96t26 62l136 136q24 28 92 4t130-86z m-448-408q32-32 80 14 46 46 14 82-14 14-38 10t-44-24-23-43 11-39z m336 298q30-30 68-50t62-25 28-1q2 4-4 27t-26 60-50 67-66 50-59 26-27 2 1-28 25-62 48-66z" horiz-adv-x="902" /> - -<glyph glyph-name="mail" unicode="" d="M30 586q-32 18-28 40 2 14 26 14l846 0q38 0 20-32-8-14-24-22-14-6-192-102t-182-98q-16-10-46-10-28 0-46 10-4 2-182 98t-192 102z m850-100q20 10 20-10l0-368q0-16-17-32t-33-16l-800 0q-16 0-33 16t-17 32l0 368q0 20 20 10l384-200q18-10 46-10t46 10z" horiz-adv-x="900" /> - -<glyph glyph-name="heart" unicode="" d="M790 644q70-64 70-156t-70-158l-360-330-360 330q-70 66-70 158t70 156q62 58 151 58t153-58l56-52 58 52q62 58 150 58t152-58z" horiz-adv-x="860" /> - -<glyph glyph-name="heart-empty" unicode="" d="M790 642q70-64 70-156t-70-156l-360-330-360 330q-70 64-70 156t70 156q64 58 152 58t150-58l58-52 56 52q64 58 152 58t152-58z m-54-260q42 40 42 104 0 66-38 100-38 38-102 38-52 0-104-48l-104-92-106 92q-48 48-102 48-64 0-104-38-38-36-38-100 0-66 44-104l306-286z" horiz-adv-x="860" /> - -<glyph glyph-name="star" unicode="" d="M440 790l120-336 320 0-262-196 94-348-272 208-272-208 94 348-262 196 320 0z" horiz-adv-x="880" /> - -<glyph glyph-name="star-empty" unicode="" d="M880 454l-262-196 94-348-272 208-272-208 94 348-262 196 320 0 120 336 120-336 320 0z m-440-238l150-124-62 178 144 114-176-4-56 202-54-202-176 4 142-114-62-178z" horiz-adv-x="880" /> - -<glyph glyph-name="user" unicode="" d="M736 128q204-72 204-122l0-106-940 0 0 106q0 50 204 122 94 34 128 69t34 95q0 22-22 49t-32 73q-2 12-9 18t-14 8-14 17-9 43q0 16 5 26t9 12l4 4q-8 50-12 88-4 54 41 112t157 58 158-58 40-112l-12-88q18-8 18-42-2-28-9-43t-14-17-14-8-9-18q-8-48-31-74t-23-48q0-60 35-95t127-69z" horiz-adv-x="940" /> - -<glyph glyph-name="users" unicode="" d="M1000-90l-224 0 0 150q0 54-30 81t-154 89q40 30 40 84 0 16-13 33t-19 51q-2 8-14 16t-14 42q0 24 12 30-6 34-8 60-4 38 23 78t95 40 96-40 24-78l-8-60q12-6 12-30-2-34-14-42t-14-16q-6-34-19-51t-13-33q0-42 21-66t77-48q112-46 130-80 6-8 9-61t5-101l0-48z m-488 262q182-78 182-124l0-138-694 0 0 184q0 44 84 78 76 32 104 64t28 88q0 20-19 44t-25 68q-2 10-18 22t-20 56q0 14 3 23t7 13l4 2q-6 46-10 82-4 50 33 103t127 53 127-53 33-103l-10-82q14-8 14-38-4-44-20-56t-18-22q-6-44-25-68t-19-44q0-56 28-88t104-64z" horiz-adv-x="1000" /> - -<glyph glyph-name="user-add" unicode="" d="M620 128q180-64 180-122l0-106-800 0 0 202q36 14 82 26 94 34 129 69t35 95q0 22-23 48t-31 74q-2 12-23 25t-25 61q0 16 5 26t9 12l4 4q-8 50-12 88-6 54 40 112t160 58 160-58 42-112l-14-88q18-8 18-42-2-28-9-43t-14-17-14-8-9-18q-10-46-33-73t-23-49q0-60 36-95t130-69z m230 272l150 0 0-100-150 0 0-150-100 0 0 150-150 0 0 100 150 0 0 150 100 0 0-150z" horiz-adv-x="1000" /> - -<glyph glyph-name="video" unicode="" d="M980 600l-100 0 0-100 100 0 0-100-100 0 0-100 100 0 0-100-100 0 0-100 100 0 0-60q0-16-12-28t-28-12l-900 0q-16 0-28 12t-12 28l0 60 100 0 0 100-100 0 0 100 100 0 0 100-100 0 0 100 100 0 0 100-100 0 0 60q0 18 12 29t28 11l900 0q16 0 28-11t12-29l0-60z m-600-400l250 150-250 150 0-300z" horiz-adv-x="980" /> - -<glyph glyph-name="picture" unicode="" d="M856 518l-100 0-124 150-214-150-180 0q-52 0-90-39t-38-91l0-160-108 296q-10 38 22 52l680 248q36 10 50-24z m106-90q16 0 27-12t11-28l0-472q0-16-11-28t-27-12l-724 0q-16 0-27 12t-11 28l0 472q0 16 11 28t27 12l724 0z m-56-452l0 162-72 160-166-60-130-132-138 170-92-214 0-86 598 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="camera" unicode="" d="M500 450q64 0 107-44t43-106-44-106-106-44-106 44-44 106 44 106 106 44z m400 150q42 0 71-29t29-71l0-450q0-40-29-70t-71-30l-800 0q-40 0-70 30t-30 70l0 450q0 42 30 71t70 29l120 0q28 0 40 30l30 92q10 28 40 28l340 0q30 0 40-28l30-92q12-30 40-30l120 0z m-400-550q104 0 177 73t73 177-73 177-177 73-177-73-73-177 73-177 177-73z m366 380q14 0 24 11t10 25-10 24-24 10q-36 0-36-34 0-16 11-26t25-10z" horiz-adv-x="1000" /> - -<glyph glyph-name="layout" unicode="" d="M170 650q80 0 80-80l0-90q0-80-80-80l-90 0q-80 0-80 80l0 90q0 80 80 80l90 0z m350 0q80 0 80-80l0-90q0-80-80-80l-90 0q-80 0-80 80l0 90q0 80 80 80l90 0z m-350-350q80 0 80-80l0-90q0-80-80-80l-90 0q-80 0-80 80l0 90q0 80 80 80l90 0z m350 0q80 0 80-80l0-90q0-80-80-80l-90 0q-80 0-80 80l0 90q0 80 80 80l90 0z" horiz-adv-x="600" /> - -<glyph glyph-name="menu" unicode="" d="M650 400q22 0 36-15t14-35-15-35-35-15l-600 0q-20 0-35 15t-15 35 14 35 36 15l600 0z m-600 100q-20 0-35 15t-15 35 14 35 36 15l600 0q22 0 36-15t14-35-15-35-35-15l-600 0z m600-300q22 0 36-15t14-35-15-35-35-15l-600 0q-20 0-35 15t-15 35 14 35 36 15l600 0z" horiz-adv-x="700" /> - -<glyph glyph-name="check" unicode="" d="M249 0q-34 0-56 28l-180 236q-16 24-12 52t26 46 51 14 47-28l118-154 296 474q16 24 43 30t53-8q24-16 30-43t-8-53l-350-560q-20-32-56-32z" horiz-adv-x="667" /> - -<glyph glyph-name="cancel" unicode="" d="M452 194q18-18 18-43t-18-43q-18-16-43-16t-43 16l-132 152-132-152q-18-16-43-16t-43 16q-16 18-16 43t16 43l138 156-138 158q-16 18-16 43t16 43q18 16 43 16t43-16l132-152 132 152q18 16 43 16t43-16q18-18 18-43t-18-43l-138-158z" horiz-adv-x="470" /> - -<glyph glyph-name="cancel-circled" unicode="" d="M420 770q174 0 297-123t123-297-123-297-297-123-297 123-123 297 123 297 297 123z m86-420l154 154-86 86-154-152-152 152-88-86 154-154-154-152 88-86 152 152 154-152 86 86z" horiz-adv-x="840" /> - -<glyph glyph-name="cancel-squared" unicode="" d="M700 750q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l600 0z m-146-638l86 86-154 152 154 154-86 86-154-152-152 152-88-86 154-154-154-152 88-86 152 152z" horiz-adv-x="800" /> - -<glyph glyph-name="plus" unicode="" d="M550 400q30 0 30-50t-30-50l-210 0 0-210q0-30-50-30t-50 30l0 210-210 0q-30 0-30 50t30 50l210 0 0 210q0 30 50 30t50-30l0-210 210 0z" horiz-adv-x="580" /> - -<glyph glyph-name="plus-circled" unicode="" d="M420 770q174 0 297-123t123-297-123-297-297-123-297 123-123 297 123 297 297 123z m52-470l200 0 0 102-200 0 0 202-102 0 0-202-202 0 0-102 202 0 0-202 102 0 0 202z" horiz-adv-x="840" /> - -<glyph glyph-name="plus-squared" unicode="" d="M700 750q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l600 0z m-50-450l0 100-200 0 0 200-100 0 0-200-200 0 0-100 200 0 0-200 100 0 0 200 200 0z" horiz-adv-x="800" /> - -<glyph glyph-name="minus" unicode="" d="M550 400q30 0 30-50t-30-50l-520 0q-30 0-30 50t30 50l520 0z" horiz-adv-x="580" /> - -<glyph glyph-name="minus-circled" unicode="" d="M420 770q174 0 297-123t123-297-123-297-297-123-297 123-123 297 123 297 297 123z m252-368l-504 0 0-102 504 0 0 102z" horiz-adv-x="840" /> - -<glyph glyph-name="minus-squared" unicode="" d="M700 750q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l600 0z m-50-450l0 100-500 0 0-100 500 0z" horiz-adv-x="800" /> - -<glyph glyph-name="help" unicode="" d="M494 740q86-62 86-184 0-64-42-124-12-20-88-80l-46-30q-40-34-48-60-6-16-8-44 0-14-16-14l-128 0q-16 0-16 12 4 98 28 124 16 22 48 48t56 42l24 14q22 16 34 34 28 44 28 70 0 40-26 78-28 36-92 36-68 0-94-44-28-42-28-92l-166 0q6 162 114 232 70 42 166 42 130 0 214-60z m-216-636q44 0 73-30t27-74q-2-46-32-73t-74-25q-44 0-73 29t-27 75 32 73 74 25z" horiz-adv-x="580" /> - -<glyph glyph-name="help-circled" unicode="" d="M454 810q190 2 326-130t140-322q2-190-131-327t-323-141q-190-2-327 131t-139 323q-4 190 130 327t324 139z m-2-740q30 0 49 19t19 47q2 30-17 49t-49 19l-2 0q-28 0-47-18t-21-46q0-30 19-49t47-21l2 0z m166 328q26 34 26 78 0 78-54 116-52 38-134 38-64 0-104-26-68-42-72-146l0-4 110 0 0 4q0 26 16 54 16 24 54 24 40 0 52-20 16-20 16-44 0-18-16-40-8-12-20-20l-6-4q-6-4-16-11t-20-15-21-17-17-17q-14-20-18-78l0-8 108 0 0 4q0 12 4 28 6 20 28 36l28 18q46 34 56 50z" horiz-adv-x="920" /> - -<glyph glyph-name="info" unicode="" d="M352 850q48 0 74-27t26-69q0-50-39-88t-95-38q-48 0-74 26t-24 72q0 46 35 85t97 39z m-206-1000q-100 0-54 178l60 254q14 56 0 56-12 0-54-18t-72-38l-26 44q90 78 189 126t151 48q78 0 36-162l-70-266q-16-64 6-64 44 0 118 60l30-40q-84-86-175-132t-139-46z" horiz-adv-x="460" /> - -<glyph glyph-name="info-circled" unicode="" d="M454 810q190 2 326-130t140-322q2-190-131-327t-323-141q-190-2-327 131t-139 323q-4 190 130 327t324 139z m52-152q-42 0-65-24t-23-50q-2-28 15-44t49-16q38 0 61 22t23 54q0 58-60 58z m-120-594q30 0 84 26t106 78l-18 24q-48-36-72-36-14 0-4 38l42 160q26 96-22 96-30 0-89-29t-115-75l16-26q52 34 74 34 12 0 0-34l-36-152q-26-104 34-104z" horiz-adv-x="920" /> - -<glyph glyph-name="back" unicode="" d="M750 540q40 0 70-29t30-71l0-290q0-40-30-70t-70-30l-690 0 0 140 650 0 0 210-500 0 0-110-210 180 210 180 0-110 540 0z" horiz-adv-x="850" /> - -<glyph glyph-name="home" unicode="" d="M888 336q16-16 11-27t-27-11l-84 0 0-310q0-14-1-21t-8-13-23-6l-204 0 0 310-204 0 0-310-194 0q-28 0-35 10t-7 30l0 310-84 0q-22 0-27 11t11 27l400 402q16 16 38 16t38-16z" horiz-adv-x="900" /> - -<glyph glyph-name="link" unicode="" d="M294 116q14 14 34 14t36-14q32-34 0-70l-42-40q-56-56-132-56-78 0-134 56t-56 132q0 78 56 134l148 148q70 68 144 77t128-43q16-16 16-36t-16-36q-36-32-70 0-50 48-132-34l-148-146q-26-26-26-64t26-62q26-26 63-26t63 26z m450 574q56-56 56-132 0-78-56-134l-158-158q-74-72-150-72-62 0-112 50-14 14-14 34t14 36q14 14 35 14t35-14q50-48 122 24l158 156q28 28 28 64 0 38-28 62-24 26-56 31t-60-21l-50-50q-16-14-36-14t-34 14q-34 34 0 70l50 50q54 54 127 51t129-61z" horiz-adv-x="800" /> - -<glyph glyph-name="attach" unicode="" d="M244-140q-102 0-170 72-72 70-74 166t84 190l496 496q80 80 174 54 44-12 79-47t47-79q26-96-54-176l-474-474q-40-40-88-46-48-4-80 28-30 24-27 74t47 92l332 334q24 26 50 0t0-50l-332-332q-44-44-20-70 12-8 24-6 24 4 46 26l474 474q50 50 34 108-16 60-76 76-54 14-108-36l-494-494q-66-76-64-143t52-117q50-48 117-50t141 62l496 494q24 24 50 0 26-22 0-48l-496-496q-82-82-186-82z" horiz-adv-x="939" /> - -<glyph glyph-name="lock" unicode="" d="M640 476q20 0 40-19t20-41l0-390q0-48-48-66l-60-18q-42-16-96-16l-290 0q-56 0-98 16l-60 18q-48 18-48 66l0 390q0 22 15 41t35 19l100 0 0 70q0 110 51 170t149 60 149-60 51-170l0-70 90 0z m-390 90l0-90 200 0 0 90q0 52-27 81t-73 29-73-29-27-81z" horiz-adv-x="700" /> - -<glyph glyph-name="lock-open" unicode="" d="M640 450q20 0 40-20t20-40l0-390q0-20-14-39t-34-25l-60-20q-52-16-96-16l-290 0q-46 0-98 16l-60 20q-20 6-34 25t-14 39l0 390q0 22 15 41t35 19l400 0 0 140q0 110-100 110t-100-110l0-40-100 0 0 20q0 110 51 170t149 60q200 0 200-230l0-120 90 0z" horiz-adv-x="700" /> - -<glyph glyph-name="eye" unicode="" d="M500 630q92 0 177-25t141-62 99-77 63-71 20-45-20-44-63-71-99-78-141-62-177-25-177 25-141 62-99 78-63 71-20 44 20 45 63 71 99 77 141 62 177 25z m0-494q92 0 157 63t65 151q0 90-65 153t-157 63-157-63-65-153q0-88 65-151t157-63z m0 214q8-8 37-2t50 11 25-9q0-44-33-75t-79-31-78 31-32 75q0 46 32 77t78 31q14 0 10-23t-12-47 2-38z" horiz-adv-x="1000" /> - -<glyph glyph-name="tag" unicode="" d="M944 830q36-106-8-199t-128-157l18-24q16-28 6-54l-48-158q-12-30-36-46l-464-328q-42-30-64 4l-210 304q-12 18-9 39t21 33l464 328q26 18 54 18l158 0q30 0 48-26l28-40q168 130 114 286-10 28 18 40 32 8 38-20z m-216-468q40 32 34 80l-32-16q-8-4-12-4-18 0-28 18-12 30 16 40l24 14q-48 34-92 0-28-18-34-51t14-61q18-26 51-32t59 12z" horiz-adv-x="960" /> - -<glyph glyph-name="bookmark" unicode="" d="M310 800q22 0 36-15t14-35l0-850-180 180-180-180 0 850q0 50 40 50l270 0z" horiz-adv-x="360" /> - -<glyph glyph-name="bookmarks" unicode="" d="M500 850q20 0 35-15t15-35l0-850-150 180 0 620q0 20-15 35t-35 15l-100 0q0 50 40 50l210 0z m-250-150q20 0 35-15t15-35l0-800-150 180-150-180 0 800q0 50 40 50l210 0z" horiz-adv-x="550" /> - -<glyph glyph-name="flag" unicode="" d="M874 616q14 6 22-1t0-19q-96-138-164-213t-110-90-73-2-60 37-63 40-93-4-139-86l90-352-100 0-184 720 92 34q90 66 152 86t98 3 64-51 62-71 79-62 129-20 198 51z" horiz-adv-x="900" /> - -<glyph glyph-name="thumbs-up" unicode="" d="M582 480q2-6 58-13t108-24 52-47q0-72-61-284t-107-212q-144 0-288 42t-144 88l0 342q0 14 15 34t46 45 53 41 62 43 46 31q50 34 104 100t85 104 41 26q48-76 29-137t-59-119-40-60z m-432-4q14 0 0-14-50-50-50-104l0-318q0-50 52-104 10-10-2-10-26 0-55 8t-62 45-33 99l0 242q0 62 33 100t63 47 54 9z" horiz-adv-x="800" /> - -<glyph glyph-name="thumbs-down" unicode="" d="M218 218q-2 6-57 13t-108 24-53 47q0 72 62 285t106 213q144 0 288-43t144-89l0-342q0-10-8-24t-25-30-32-29-42-32-41-29-41-28l-33-22q-50-34-104-100t-85-104-41-26q-48 76-29 137t59 119 40 60z m432 4q-12 0 2 14 48 50 48 104l0 318q0 50-52 104-10 10 2 10 26 0 55-8t62-45 33-99l0-242q0-48-18-81t-45-48-48-21-39-6z" horiz-adv-x="800" /> - -<glyph glyph-name="download" unicode="" d="M968 198q18-10 27-32t3-40l-28-154q-4-20-22-33t-40-13l-816 0q-22 0-40 13t-22 33l-28 154q-10 48 32 72l158 108 98 0-170-130 178 0q8 0 12-8l40-110 300 0 40 110q8 8 12 8l178 0-170 130 98 0z m-208 322l-260-244-260 244 166 0 0 256 190 0 0-256 164 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="upload" unicode="" d="M500 776l260-244-164 0 0-256-190 0 0 256-166 0z m468-578q18-10 27-32t3-40l-28-154q-4-20-22-33t-40-13l-816 0q-22 0-40 13t-22 33l-28 154q-10 48 32 72l158 108 98 0-170-130 178 0q8 0 12-8l40-110 300 0 40 110q8 8 12 8l178 0-170 130 98 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="upload-cloud" unicode="" d="M760 494q100 0 170-68t70-166-70-166-170-68l-190 0 0 190 106 0-176 230-174-230 104 0 0-190-248 0q-74 0-128 52t-54 124q0 74 53 126t129 52q14 0 20-2-2 12-2 38 0 108 78 184t188 76q90 0 160-52t94-134q28 4 40 4z" horiz-adv-x="1000" /> - -<glyph glyph-name="reply" unicode="" d="M900 10q-86 152-208 197t-330 45l0-218-362 334 362 322 0-192q90 0 168-27t131-70 96-95 69-104 44-95 24-69z" horiz-adv-x="900" /> - -<glyph glyph-name="reply-all" unicode="" d="M362 556l-212-188 212-196 0-138-362 334 362 322 0-134z m250-58q104 0 182-50t115-122 60-144 27-122l4-50q-86 154-168 198t-220 44l0-218-362 334 362 322 0-192z" horiz-adv-x="1000" /> - -<glyph glyph-name="forward" unicode="" d="M540 252q-210 0-332-45t-208-197q4 20 13 53t50 117 96 148 156 117 225 53l0 192 360-322-360-334 0 218z" horiz-adv-x="900" /> - -<glyph glyph-name="quote" unicode="" d="M146 680q146 0 184-146 38-140-40-302-80-168-224-204-32-8-66-8l0 70q112 0 182 108 54 86 26 146-16 36-62 36-60 0-103 44t-43 106 43 106 103 44z m420 0q146 0 184-146 38-140-40-302-80-168-224-204-32-8-66-8l0 70q112 0 182 108 54 86 26 146-16 36-62 36-60 0-103 44t-43 106 43 106 103 44z" horiz-adv-x="762" /> - -<glyph glyph-name="code" unicode="" d="M380 636q16-14 16-32t-16-30l-246-224 246-226q16-12 16-30t-16-32q-30-30-60 0l-320 288 320 286q30 30 60 0z m302 0l318-286-318-288q-32-30-62 0-32 32 0 62l248 226-248 224q-32 30 0 62 30 30 62 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="export" unicode="" d="M750 60l0 56 100 82 0-188q0-20-15-35t-35-15l-750 0q-20 0-35 15t-15 35l0 550q0 22 14 36t36 14l288 0q-32-24-59-49t-39-39l-10-12-130 0 0-450 650 0z m-82 348q-166 0-242-41t-160-181q0 8 1 22t9 56 22 79 44 83 70 79 107 56 149 23l0 156 332-250-332-260 0 178z" horiz-adv-x="1000" /> - -<glyph glyph-name="pencil" unicode="" d="M718 680q32-32 47-64t15-48l0-16-252-252-290-288-238-52 50 240 290 288 252 252q54 12 126-60z m-494-640l24 24q-2 44-52 94-22 22-45 35t-35 13l-14 2-22-24-18-80q28-16 46-34 24-24 36-48z" horiz-adv-x="780" /> - -<glyph glyph-name="feather" unicode="" d="M60-138q-6-20-26-8-18 8-16 34 4 100 50 226-100 154-52 316 10-32 32-78t44-80 32-30q8 4 0 83t-11 166 25 157q22 44 80 94t104 70q-24-46-33-94t-4-78 21-32q12 0 84 120t106 122q46 4 114-29t82-65q12-24 0-79t-40-83q-44-44-146-62t-114-24q-16-10 12-34 54-48 176-20-56-80-136-114t-132-38-54-10q-4-24 49-54t101-14q-30-56-63-84t-54-35-76-11-85-8z" horiz-adv-x="698" /> - -<glyph glyph-name="print" unicode="" d="M66 526q-26 0-22 22 4 10 12 14 2 0 49 17t93 32 58 15l44 0 0 150 380 0 0-150 46 0q12 0 57-15t92-32 49-17q18-8 12-26-4-10-20-10l-850 0z m860-56q20 0 37-19t17-41l0-174q0-22-17-41t-37-19l-100 0 44-250-760 0 44 250-98 0q-20 0-38 19t-18 41l0 174q0 22 18 41t38 19l870 0z m-716-444l560 0-70 324-420 0z" horiz-adv-x="980" /> - -<glyph glyph-name="retweet" unicode="" d="M250 190l272 0 128-140-448 0q-42 0-71 30t-29 70l0 302-102 0 176 198 174-198-100 0 0-262z m650 60l100 0-174-200-176 200 102 0 0 260-274 0-128 140 450 0q40 0 70-29t30-71l0-300z" horiz-adv-x="1000" /> - -<glyph glyph-name="keyboard" unicode="" d="M930 650q28 0 49-21t21-49l0-460q0-30-21-50t-49-20l-860 0q-28 0-49 20t-21 50l0 460q0 28 21 49t49 21l860 0z m-380-100l0-100 100 0 0 100-100 0z m150-150l-100 0 0-100 100 0 0 100z m-300 150l0-100 100 0 0 100-100 0z m150-150l-100 0 0-100 100 0 0 100z m-300 150l0-100 100 0 0 100-100 0z m150-150l-100 0 0-100 100 0 0 100z m-300 150l0-100 100 0 0 100-100 0z m150-150l-100 0 0-100 100 0 0 100z m-50-250l0 100-100 0 0-100 100 0z m550 0l0 100-500 0 0-100 500 0z m150 0l0 100-100 0 0-100 100 0z m-150 150l100 0 0 100-100 0 0-100z m150 150l0 100-200 0 0-100 200 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="comment" unicode="" d="M700 700q42 0 71-29t29-71l0-350q0-40-29-70t-71-30l-200 0 0-150-200 150-200 0q-40 0-70 30t-30 70l0 350q0 42 30 71t70 29l600 0z" horiz-adv-x="800" /> - -<glyph glyph-name="chat" unicode="" d="M290 240l350 0q2 0 6 2l4 0 0-92q0-40-29-70t-71-30l-250 0-150-150 0 150-50 0q-40 0-70 30t-30 70l0 300q0 42 30 71t70 29l190 0 0-310z m610 560q42 0 71-29t29-71l0-300q0-40-29-70t-71-30l-50 0 0-150-150 150-350 0 0 400q0 42 30 71t70 29l450 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="bell" unicode="" d="M632 426q16-34 40-52t45-22 44-23 35-55q22-62-74-161t-252-157q-164-58-297-45t-155 75q-20 54 12 111t18 111q-56 192-47 300t113 192q26 22 29 51t29 39q24 8 46-12t56-18q132 2 198-66t160-268z m-186-404q88 32 159 85t100 91 25 50q-8 22-49 33t-124 1-187-48q-102-38-173-87t-94-84-17-53q4-12 50-22t134-4 176 38z m-62 174q8 2 21 7t17 7l2-2q14-40-17-83t-89-63q-96-36-152 14 78 68 218 120z" horiz-adv-x="800" /> - -<glyph glyph-name="attention" unicode="" d="M957-24q10-16 0-34-10-16-30-16l-892 0q-18 0-28 16-13 18-2 34l446 782q8 18 30 18t30-18z m-420 50l0 100-110 0 0-100 110 0z m0 174l0 300-110 0 0-300 110 0z" horiz-adv-x="962" /> - -<glyph glyph-name="alert" unicode="" d="M885 234q20-16 16-33t-28-23l-78-22q-24-6-40-28t-14-48l4-82q2-24-14-34t-38 0l-86 44q-22 12-47 4t-35-30l-46-88q-12-22-29-23t-33 19l-50 78q-34 48-88 20l-122-70q-22-14-32-6t-2 32l54 164q8 24-4 44t-36 22l-106 12q-24 4-29 18t15 30l86 76q20 16 20 41t-20 41l-86 76q-20 16-16 33t28 23l78 22q24 6 41 28t15 48l-6 82q0 26 15 36t37 0l80-38q24-10 49-2t37 30l46 80q12 22 30 21t30-23l50-86q12-22 35-29t45 7l136 84q22 14 30 6t0-32l-60-170q-10-22 2-41t38-21l114-12q26-2 30-16t-16-30l-86-76q-18-16-18-41t18-41z m-384-92l0 104-100 0 0-104 100 0z m0 160l0 260-100 0 0-260 100 0z" horiz-adv-x="901" /> - -<glyph glyph-name="vcard" unicode="" d="M900 750q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-800 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l800 0z m0-700l0 600-800 0 0-600 800 0z m-450 196l0-90-250 0 0 90 250 0z m0 150l0-90-250 0 0 90 250 0z m0 150l0-90-250 0 0 90 250 0z m346-320l4-70-250 0q0 70 6 70 84 22 84 66 0 16-27 56t-27 88q0 110 90 110t90-110q0-48-28-88t-28-56q0-20 21-36t43-22z" horiz-adv-x="1000" /> - -<glyph glyph-name="address" unicode="" d="M426 800q20 0 20-20l0-860q0-20-20-20l-46 0q-20 0-20 20l0 440-176 0q-16 0-28 6-12 2-26 12l-120 82q-10 6-10 16t10 16l120 82q14 10 26 12 8 4 28 4l176 0 0 190q0 20 20 20l46 0z m564-208q10-6 10-16t-10-16l-118-82q-22-12-26-12-14-6-28-6l-302 0-40 230 342 0q18 0 28-4t26-12z" horiz-adv-x="1000" /> - -<glyph glyph-name="location" unicode="" d="M250 750q104 0 177-73t73-177q0-106-62-243t-126-223l-62-84q-10 12-27 35t-60 89-76 130-60 147-27 149q0 104 73 177t177 73z m0-388q56 0 96 40t40 96-40 95-96 39-95-39-39-95 39-96 95-40z" horiz-adv-x="500" /> - -<glyph glyph-name="map" unicode="" d="M984 600q16-10 16-30l0-584q0-20-16-30-8-6-16-6t-18 6l-216 136-216-136q-18-10-34 0l-218 136-216-136q-16-10-34 0-16 10-16 30l0 584q0 20 16 30l234 146q18 10 34 0l216-136 218 136q16 10 32 0z m-750-450l0 506-168-104 0-506z m234-104l0 506-168 104 0-506z m234 104l0 506-170-104 0-506z m232-104l0 506-168 104 0-506z" horiz-adv-x="1000" /> - -<glyph glyph-name="direction" unicode="" d="M848 768q8-8 11-16t-2-22-10-26-19-39-24-49q-54-112-147-286t-157-292l-66-118-54 380-380 56q442 246 696 368 20 10 48 25t39 20 25 9 23 1 17-11z m-92-96l-304-280 28-234z" horiz-adv-x="860" /> - -<glyph glyph-name="compass" unicode="" d="M474 830q198 2 340-136t146-336q2-200-136-342t-338-146q-198-2-341 137t-145 337q-4 200 135 342t339 144z m12-858q156 2 266 114t108 270-115 267-269 107q-158-2-267-114t-107-270 114-267 270-107z m-234 154q4 26 12 66t41 128 77 132 125 76 141 42l60 10q-4-26-12-66t-41-128-77-132q-42-42-124-74t-142-42z m180 276q-22-20-22-48t22-50q20-22 49-22t49 22q52 52 88 186-136-36-186-88z" horiz-adv-x="960" /> - -<glyph glyph-name="cup" unicode="" d="M340 760q152 0 249-41t91-87l-72-594q-2-14-34-36t-97-42-137-20-136 20-97 42-35 36l-72 594q-4 28 36 57t121 50 183 21z m0-216q72 0 137 15t98 33 33 30-33 29-98 32-137 15-137-15-98-32-33-29 33-30 98-33 137-15z" horiz-adv-x="681" /> - -<glyph glyph-name="trash" unicode="" d="M50 458q122-70 330-70t330 70l-54-486q-2-14-35-36t-100-43-141-21-140 21-100 43-36 36z m488 300q94-18 158-55t64-71l0-10q0-58-112-99t-268-41-268 41-112 99l0 10q0 34 64 71t158 55l42 48q22 26 70 26l92 0q52 0 70-26z m-54-112l84 0q-92 110-104 126-14 16-32 16l-102 0q-22 0-32-16l-106-126 84 0 64 66 82 0z" horiz-adv-x="760" /> - -<glyph glyph-name="doc" unicode="" d="M600 800q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-500 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l500 0z m0-800l0 700-500 0 0-700 500 0z" horiz-adv-x="700" /> - -<glyph glyph-name="docs" unicode="" d="M970 480q38-10 30-46l-150-556q-4-16-18-23t-30-3l-406 110q-16 4-24 18t-4 28l24 92-180-48q-40-10-50 26l-160 602q-10 36 28 48l454 122q16 4 30-3t18-23l66-244z m-888 190l144-542 392 106-144 540z m702-742l132 492-298 82 76-282q10-34-28-46l-196-52-26-102z" horiz-adv-x="1001" /> - -<glyph glyph-name="doc-landscape" unicode="" d="M0 600q0 42 30 71t70 29l800 0q42 0 71-29t29-71l0-500q0-40-29-70t-71-30l-800 0q-40 0-70 30t-30 70l0 500z m900 0l-800 0 0-500 800 0 0 500z" horiz-adv-x="1000" /> - -<glyph glyph-name="doc-text" unicode="" d="M212 308l0 90 280 0 0-90-280 0z m388 492q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-500 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l500 0z m0-800l0 700-500 0 0-700 500 0z m-110 592l0-88-280 0 0 88 280 0z m0-392l0-88-280 0 0 88 280 0z" horiz-adv-x="700" /> - -<glyph glyph-name="doc-text-inv" unicode="" d="M600 800q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-500 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l500 0z m-460-208l0-88 420 0 0 88-420 0z m420-480l0 88-420 0 0-88 420 0z m0 196l0 90-418 0 0-90 418 0z" horiz-adv-x="700" /> - -<glyph glyph-name="newspaper" unicode="" d="M700 800q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l600 0z m0-800l0 700-600 0 0-700 600 0z m-250 250l0-50-250 0 0 50 250 0z m150 200l0-50-200 0 0 50 200 0z m-200 50l0 100 200 0 0-100-200 0z m-50 100l0-200-150 0 0 200 150 0z m-50-250l0-50-100 0 0 50 100 0z m50-50l0 50 250 0 0-50-250 0z m250-150l0-50-400 0 0 50 400 0z m-100 50l0 50 100 0 0-50-100 0z" horiz-adv-x="800" /> - -<glyph glyph-name="book-open" unicode="" d="M340 238l0-68-200 80 0 68z m0 208l0-68-200 80 0 68z m538 346q22-12 22-42l0-640q0-34-32-46l-398-160q-8-2-10-2t-5-1-5-1-5 1-5 1l-10 2-398 160q-32 12-32 46l0 640q0 30 22 42 22 16 46 6l382-154 382 154q24 10 46-6z m-478-788l0 560-320 128 0-560z m420 128l0 560-320-128 0-560z m-60 186l0-68-200-80 0 68z m0 208l0-68-200-80 0 68z" horiz-adv-x="900" /> - -<glyph glyph-name="book" unicode="" d="M682 594q18-8 18-28l0-562q0-14-12-25t-28-11q-46 0-46 36l0 522q0 12-12 18l-404 216q-32 10-68-10-44-20-56-44l408-228q18-8 18-28l0-550q0-22-18-28-6-4-16-4-14 0-20 4-8 6-202 127t-212 131q-26 18-26 34l-6 524q0 28 14 52 28 46 102 77t116 9z" horiz-adv-x="700" /> - -<glyph glyph-name="folder" unicode="" d="M954 500q32 0 40-12t6-36l-42-452q-2-24-12-37t-42-13l-806 0q-52 0-56 50l-42 452q-2 24 6 36t40 12l908 0z m-34 110l10-40-846 0 14 132q4 20 20 34t36 14l164 0q52 0 86-34l30-30q32-36 86-36l340 0q20 0 38-12t22-28z" horiz-adv-x="1001" /> - -<glyph glyph-name="archive" unicode="" d="M840 600l0-50-696 0 0 50q0 22 13 35t25 15l608 0q6 0 14-1t22-14 14-35z m-148 150q6 0 14-1t22-14 14-35l-498 0q0 22 13 35t25 15l410 0z m248-200q34-32 38-46 6-18 0-54l-76-450q-4-22-20-35t-28-15l-710 0q-52 0-60 50-6 26-39 223t-39 227q-10 22-3 44t10 26 21 20l10 10 30 30 0-80 836 0 0 80z m-248-270l0 100-70 0 0-80-260 0 0 80-68 0 0-100q0-50 48-50l300 0q22 0 35 12t13 24z" horiz-adv-x="981" /> - -<glyph glyph-name="box" unicode="" d="M870 750q12 0 21-9t9-21l0-120-900 0 0 120q0 12 9 21t21 9l840 0z m-820-730l0 530 800 0 0-530q0-30-21-50t-49-20l-660 0q-28 0-49 20t-21 50z m250 430l0-100 300 0 0 100-300 0z" horiz-adv-x="900" /> - -<glyph glyph-name="rss" unicode="" d="M0 730q314 0 537-223t223-537l-118 0q0 266-188 453t-454 187l0 120z m0-238q218 0 371-153t153-369l-118 0q0 166-119 285t-287 119l0 118z m114-296q46 0 80-33t34-81q0-46-34-79t-80-33-80 33-34 79q0 48 34 81t80 33z" horiz-adv-x="760" /> - -<glyph glyph-name="phone" unicode="" d="M461 290q162 162 118 206l-8 8q-30 30-41 48t-4 54 49 88q20 24 37 39t35 16 30 1 29-13 24-18 26-25 21-22q48-48-6-194t-204-294q-150-150-295-205t-193-7q-2 2-23 22t-25 25-18 24-13 31 2 30 15 35 38 37q42 34 70 47t54 2 35-18 39-37q44-44 208 120z" horiz-adv-x="800" /> - -<glyph glyph-name="cog" unicode="" d="M760 350q0-72 80-122-12-40-34-82-70 18-136-44-54-58-34-136-40-20-84-36-46 82-132 82t-132-82q-44 16-84 36 20 80-34 136-54 54-136 34-14 26-34 82 82 52 82 132 0 72-82 124 20 56 34 82 74-18 136 44 54 56 34 136 42 22 84 34 46-80 132-80t132 80q42-12 84-34-20-78 34-136 66-62 136-44 22-42 34-82-80-50-80-124z m-340-182q76 0 129 53t53 129-53 130-129 54-129-54-53-130 53-129 129-53z" horiz-adv-x="840" /> - -<glyph glyph-name="tools" unicode="" d="M155 506q-8-8-11-22t-3-25-2-11q-2-2-17-15t-19-17q-16-14-28 4l-70 76q-11 12 2 24 2 2 18 14t20 16q6 6 27 6t37 14q14 14 18 38t10 30q2 0 9 7t26 22 41 31q134 90 186 96 122 0 148-2 12 0-8-8-120-52-152-76-80-56-36-114 34-46 38-48 8-8-2-14-2-2-38-35t-38-35q-14-8-18-4-42 48-71 60t-67-12z m286-26l410-476q18-22-2-38l-48-42q-22-14-38 4l-414 472q-8 8 0 20l72 62q12 8 20-2z m554 202q16-104-16-166-50-88-154-62-56 12-100-32l-82-78-68 78 68 70q24 24 31 53t6 65 5 58q12 56 140 112 12 6 18-3t2-15q-12-12-46-80-14-10-12-35t40-53q58-40 96 22 6 12 26 41t22 33q4 10 13 9t11-17z m-858-684l254 248 76-86-246-242q-20-20-38-4l-46 46q-22 18 0 38z" horiz-adv-x="1000" /> - -<glyph glyph-name="share" unicode="" d="M650 200q62 0 106-43t44-107q0-62-44-106t-106-44-106 44-44 106q0 6 1 14t1 12l-260 156q-42-32-92-32-62 0-106 44t-44 106 44 106 106 44q54 0 92-30l260 156q0 4-1 12t-1 12q0 62 44 106t106 44 106-43 44-107q0-62-44-106t-106-44q-52 0-90 32l-262-156q2-8 2-26 0-16-2-24l262-156q36 30 90 30z" horiz-adv-x="800" /> - -<glyph glyph-name="shareable" unicode="" d="M340 350q0 68 47 114t113 46 113-46 47-114q0-66-47-113t-113-47-113 47-47 113z m-114 60q-14-60-66-60l-160 0 0 120 118 0q40 124 145 202t237 78q164 0 284-116 16-18 16-43t-16-43q-18-16-43-16t-43 16q-78 82-198 82-100 0-176-62t-98-158z m614-60l160 0 0-120-118 0q-40-124-144-202t-238-78q-164 0-282 118-18 18-18 43t18 41q16 18 41 18t43-18q82-82 198-82 100 0 176 63t98 157q12 60 66 60z" horiz-adv-x="1000" /> - -<glyph glyph-name="basket" unicode="" d="M150 0q0 40 30 70t70 30q42 0 71-30t29-70q0-42-29-71t-71-29q-40 0-70 29t-30 71z m500 0q0 40 30 70t70 30q42 0 71-30t29-70q0-42-29-71t-71-29q-40 0-70 29t-30 71z m-322 236q-36-10-34-23t44-13l562 0 0-76q0-20-20-20l-654 0q-20 0-20 20l0 76-10 46-98 454-98 0 0 80q0 20 20 20l156 0q20 0 20-20l0-86 704 0 0-274q0-22-18-26z" horiz-adv-x="900" /> - -<glyph glyph-name="bag" unicode="" d="M835 668q28-26 24-60l-98-648q-8-30-38-30l-586 0q-28 0-40 30-94 620-96 648-5 34 22 60 6 6 54 43t56 43q18 16 56 16l480 0q38 0 56-16 78-58 110-86z m-406-436q56 0 98 34t63 89 30 89 13 66l-92 0q-38-188-112-188t-112 188l-92 0q46-278 204-278z m-352 368l704 0-110 116-484 0z" horiz-adv-x="859" /> - -<glyph glyph-name="calendar" unicode="" d="M800 700q42 0 71-29t29-71l0-600q0-40-29-70t-71-30l-700 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l46 0 0-100 160 0 0 100 290 0 0-100 160 0 0 100 44 0z m0-700l0 400-700 0 0-400 700 0z m-540 800l0-170-70 0 0 170 70 0z m450 0l0-170-70 0 0 170 70 0z" horiz-adv-x="900" /> - -<glyph glyph-name="login" unicode="" d="M800 800q42 0 71-29t29-71l0-700q0-40-29-70t-71-30l-450 0q-40 0-69 30t-29 70l0 100 98 0 0-100 450 0 0 700-450 0 0-150-98 0 0 150q0 42 29 71t69 29l450 0z m-350-670l0 120-450 0 0 150 450 0 0 120 200-194z" horiz-adv-x="900" /> - -<glyph glyph-name="logout" unicode="" d="M502 0l0 100 98 0 0-100q0-40-29-70t-71-30l-400 0q-40 0-70 30t-30 70l0 700q0 42 30 71t70 29l400 0q42 0 71-29t29-71l0-150-98 0 0 150-402 0 0-700 402 0z m398 326l-198-196 0 120-450 0 0 150 450 0 0 120z" horiz-adv-x="900" /> - -<glyph glyph-name="mic" unicode="" d="M620 488q20 0 20-20l0-138q0-92-69-164t-201-84l0-132 130 0q20 0 20-20l0-60q0-20-20-20l-360 0q-20 0-20 20l0 60q0 20 20 20l130 0 0 132q-132 12-201 84t-69 164l0 138q0 20 20 20l30 0q20 0 20-20l0-138q0-66 59-123t191-57 191 57 59 123l0 138q0 20 20 20l30 0z m-300-238q-80 0-115 25t-35 55l0 158 300 0 0-158q0-30-35-55t-115-25z m150 520l0-212-300 0 0 212q0 30 35 55t115 25 115-25 35-55z" horiz-adv-x="640" /> - -<glyph glyph-name="mute" unicode="" d="M868 778q16-16 16-36t-16-36l-782-782q-18-14-34-14-18 0-36 14-16 14-16 36t16 36l782 782q34 32 70 0z m-216-386l50 50q74-92 101-172t-7-116q-24-24-75-57t-131-71-161-45-165 23l278 276q44-32 88-54t67-25 33 1q6 10 2 34t-26 68-54 88z m-276 62l-270-270q-40 132 28 283t132 215q34 32 105 11t159-85l-52-50q-58 38-105 53t-57 5q-4-8-2-28t19-58 43-76z" horiz-adv-x="884" /> - -<glyph glyph-name="sound" unicode="" d="M176 588q42 42 149-5t217-157 157-217 5-149q-28-28-92-67t-156-78-194-29-176 84-84 176 29 194 78 156 67 92z m464-480q8 10-3 49t-49 101-96 118q-56 58-118 96t-101 49-49 3q-8-10 3-49t49-101 94-120q58-56 120-94t101-49 49-3z m6 394q-18 0-34 16-16 14-16 35t16 35l94 96q36 32 72 0 32-36 0-72l-96-94q-16-16-36-16z m-180 124q-18 10-23 30t5 38l54 96q26 44 68 20 18-10 23-30t-5-38l-54-96q-14-26-42-26-14 0-26 6z m438-150q10-18 4-38t-24-30l-96-54q-16-8-24-8-28 0-44 26-10 18-4 38t24 30l96 54q18 10 38 5t30-23z" horiz-adv-x="910" /> - -<glyph glyph-name="volume" unicode="" d="M896 180q0-34-24-57t-56-23l-780 0q-22 0-31 5t-3 15 24 20l802 452q28 18 48 7t20-45l0-374z" horiz-adv-x="896" /> - -<glyph glyph-name="clock" unicode="" d="M460 810q190 0 325-135t135-325-135-325-325-135-325 135-135 325 135 325 325 135z m0-820q150 0 255 106t105 254q0 150-105 255t-255 105q-148 0-254-105t-106-255q0-148 106-254t254-106z m36 620l0-244 150-150-50-50-170 170 0 274 70 0z" horiz-adv-x="920" /> - -<glyph glyph-name="hourglass" unicode="" d="M560 622q0-44-48-96t-97-99-49-77 49-76 97-97 48-97l0-118q0-34-86-73t-194-39-194 39-86 73l0 118q0 46 48 97t97 97 49 76-49 77-97 99-48 96l0 118q0 32 87 71t193 39 193-39 87-71l0-118z m-482 112l-18-14q-4-8 4-14 92-52 216-52 132 0 220 50 14 10-16 30-96 54-202 54-120 0-204-54z m228-384q0 18 4 33t18 33 20 25 31 31 29 28q92 92 92 122l2 50q-100-54-222-54t-222 54l4-50q0-32 90-122 6-6 22-21t23-22l19-19t17-21 11-20 9-23 3-24q0-10-1-19t-6-18-8-16-11-17l-12-15t-15-16-16-15-18-16-17-16q-90-90-90-122l0-66q8 4 66 23t92 43 34 58q0 30 26 30t26-30q0-34 33-58t94-43 67-23l0 66q0 30-92 122-4 4-21 20t-22 21-18 19-18 22-12 20-9 23-2 23z" horiz-adv-x="560" /> - -<glyph glyph-name="lamp" unicode="" d="M209-110l0 104 282 0 0-104q-70-42-142-40-70-2-140 40z m276 164l-270 0q0 72-36 140t-78 113-74 112-26 139q8 120 94 206t254 86q170 0 255-86t95-206q4-60-16-113t-52-96-65-85-57-96-24-114z m-378 496q-4-4 0-20t2-20 5-19 6-18 8-18 11-19 13-19 14-19 15-21 16-23q88-122 112-212l82 0q24 94 112 212 4 6 25 35t25 36 17 29 16 33 6 28 1 35q-16 196-244 196-226 0-242-196z" horiz-adv-x="700" /> - -<glyph glyph-name="light-down" unicode="" d="M350 510q68 0 114-47t46-113q0-68-46-114t-114-46q-66 0-113 46t-47 114q0 66 47 113t113 47z m0-264q44 0 73 30t29 74q0 42-29 72t-73 30q-42 0-72-30t-30-72q0-44 30-74t72-30z m-300 144q20 0 35-12t15-28q0-40-50-40t-50 40q0 16 15 28t35 12z m546 204q28-28-8-64-14-14-33-16t-29 10q-12 12-10 31t16 33q36 34 64 6z m54-204q20 0 35-12t15-28q0-40-50-40-48 0-48 40 0 16 14 28t34 12z m-300-290q16 0 28-15t12-35-12-35-28-15-28 15-12 35 12 35 28 15z m-238 62q36 36 64 8t-8-64q-14-14-33-16t-29 8q-30 28 6 64z m-10 430q28 28 64-8 14-14 16-33t-8-29q-30-28-64 6-36 36-8 64z m432-484q-34 36-6 64t64-8q14-14 16-33t-10-29q-30-28-64 6z m-184 492q-16 0-28 15t-12 35 12 35 28 15 28-15 12-35-12-35-28-15z" horiz-adv-x="700" /> - -<glyph glyph-name="light-up" unicode="" d="M950 390q20 0 35-12t15-28q0-40-50-40l-48 0q-50 0-50 40 0 16 15 28t35 12l48 0z m-450 234q114 0 195-80t81-194q0-116-81-196t-195-80-194 80-80 196q0 114 80 194t194 80z m0-474q82 0 141 58t59 142q0 82-59 141t-141 59-141-59-59-141q0-84 59-142t141-58z m-350 200q0-40-50-40l-50 0q-50 0-50 40 0 16 15 28t35 12l50 0q20 0 35-12t15-28z m350 350q-16 0-28 15t-12 35l0 50q0 20 12 35t28 15 28-15 12-35l0-50q0-20-12-35t-28-15z m0-700q16 0 28-15t12-35l0-50q0-20-12-35t-28-15-28 15-12 35l0 50q0 20 12 35t28 15z m368 660l-34-34q-34-34-64-8-28 28 8 64 4 6 34 36 36 34 64 6t-8-64z m-700-588q14 16 33 18t29-10q12-12 10-31t-16-33l-36-36q-14-14-33-16t-29 10q-30 28 6 64 6 4 36 34z m20 646l36-36q36-36 6-64-10-10-29-8t-33 16q-30 30-36 34-14 14-16 33t10 31q10 12 29 10t33-16z m590-702q-36 36-8 64t64-8l34-34q36-36 8-64t-64 6q-30 30-34 36z" horiz-adv-x="1000" /> - -<glyph glyph-name="adjust" unicode="" d="M950 390q20 0 35-12t15-28q0-40-50-40l-48 0q-50 0-50 40 0 16 15 28t35 12l48 0z m-450 234q114 0 195-80t81-194q0-116-81-196t-195-80-194 80-80 196q0 114 80 194t194 80z m6-474l0 400q-86 0-146-59t-60-141q0-84 60-142t146-58z m-356 200q0-40-50-40l-50 0q-50 0-50 40 0 16 15 28t35 12l50 0q20 0 35-12t15-28z m350 350q-16 0-28 15t-12 35l0 50q0 20 12 35t28 15 28-15 12-35l0-50q0-20-12-35t-28-15z m0-700q16 0 28-15t12-35l0-50q0-20-12-35t-28-15-28 15-12 35l0 50q0 20 12 35t28 15z m368 660l-34-34q-34-34-64-8-28 28 8 64 4 6 34 36 36 34 64 6t-8-64z m-700-588q14 16 33 18t29-10q12-12 10-31t-16-33l-36-36q-14-14-33-16t-29 10q-30 28 6 64 6 4 36 34z m20 646l36-36q36-36 6-64-10-10-29-8t-33 16q-30 30-36 34-14 14-16 33t10 31q10 12 29 10t33-16z m590-702q-36 36-8 64t64-8l34-34q36-36 8-64t-64 6q-30 30-34 36z" horiz-adv-x="1000" /> - -<glyph glyph-name="block" unicode="" d="M480 830q200 0 340-140t140-340q0-198-140-339t-340-141q-198 0-339 141t-141 339q0 200 141 340t339 140z m258-220z m-622-260q0-132 82-230l514 514q-100 82-232 82-152 0-258-107t-106-259z m106-258z m258-106q152 0 259 107t107 257q0 130-82 232l-514-514q98-82 230-82z" horiz-adv-x="960" /> - -<glyph glyph-name="resize-full" unicode="" d="M476 746l316 0 0-316-100 124-146-152-100 100 152 146z m-230-444l100-100-152-146 122-100-316 0 0 316 100-122z" horiz-adv-x="792" /> - -<glyph glyph-name="resize-small" unicode="" d="M156 146l-106 100 296 0 0-296-100 106-146-156-100 100z m744 554l-154-144 104-100-294 0 0 294 100-104 144 154z" horiz-adv-x="900" /> - -<glyph glyph-name="popup" unicode="" d="M700 750q42 0 71-29t29-71l0-400q0-40-29-70t-71-30l-400 0q-40 0-70 30t-30 70l0 402q0 40 29 69t71 29l400 0z m0-500l0 400-400 0 0-400 400 0z m-600 100l0-300 300 0 0-100-300 0q-40 0-70 30t-30 70l0 300 100 0z" horiz-adv-x="800" /> - -<glyph glyph-name="publish" unicode="" d="M900 800q42 0 71-30t29-70l0-600q0-42-29-71t-71-29l-198 0 0 98 200 0 0 462-802 0 0-462 200 0 0-98-200 0q-40 0-70 29t-30 71l0 600q0 40 30 70t70 30l800 0z m-770-168q38 0 38 38 0 16-11 26t-27 10-27-11-11-25q0-16 11-27t27-11z m100 0q38 0 38 38 0 16-11 26t-27 10-27-11-11-25q0-16 11-27t27-11z m672 6l0 62-602 0 0-62 602 0z m-404-198l242-240-150 0 0-300-184 0 0 300-150 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="window" unicode="" d="M900 750q42 0 71-30t29-70l0-600q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 600q0 40 30 70t70 30l800 0z m-670-94q-16 0-27-11t-11-25q0-16 11-27t27-11q38 0 38 38 0 16-11 26t-27 10z m-138-36q0-16 11-27t27-11q38 0 38 38 0 16-11 26t-27 10-27-11-11-25z m810-570l0 460-802 0 0-460 802 0z m0 540l0 60-602 0 0-60 602 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="arrow-combo" unicode="" d="M230 850l230-364-460 0z m0-1000l-230 366 460 0z" horiz-adv-x="460" /> - -<glyph glyph-name="down-circled" unicode="" d="M460 810q190 0 325-135t135-325-135-325-325-135-325 135-135 325 135 325 325 135z m0-820q148 0 254 106t106 254q0 150-106 255t-254 105-254-105-106-255q0-148 106-254t254-106z m90 554l0-206 112 0-202-190-202 190 112 0 0 206 180 0z" horiz-adv-x="920" /> - -<glyph glyph-name="left-circled" unicode="" d="M920 350q0-190-135-325t-325-135-325 135-135 325q0 192 135 326t325 134 325-134 135-326z m-820 0q0-148 106-254t254-106 254 106 106 254q0 150-106 255t-254 105-254-105-106-255z m552-90l-204 0 0-112-190 202 190 204 0-114 204 0 0-180z" horiz-adv-x="920" /> - -<glyph glyph-name="right-circled" unicode="" d="M0 350q0 190 135 325t325 135 325-135 135-325-135-325-325-135-325 135-135 325z m820 0q0 150-105 255t-255 105q-148 0-254-105t-106-255q0-148 106-254t254-106q150 0 255 106t105 254z m-552 90l204 0 0 114 190-204-190-202 0 112-204 0 0 180z" horiz-adv-x="920" /> - -<glyph glyph-name="up-circled" unicode="" d="M460-110q-190 0-325 135t-135 325q0 192 135 326t325 134 325-134 135-326q0-190-135-325t-325-135z m0 820q-148 0-254-105t-106-255q0-148 106-254t254-106q150 0 255 106t105 254q0 150-105 255t-255 105z m-90-552l0 204-112 0 202 192 202-192-112 0 0-204-180 0z" horiz-adv-x="920" /> - -<glyph glyph-name="down-open" unicode="" d="M564 422l-234-224q-18-18-40-18t-40 18l-234 224q-16 16-16 41t16 41q38 38 78 0l196-188 196 188q40 38 78 0 16-16 16-41t-16-41z" horiz-adv-x="580" /> - -<glyph glyph-name="left-open" unicode="" d="M242 626q14 16 39 16t41-16q38-36 0-80l-186-196 186-194q38-44 0-80-16-16-40-16t-40 16l-226 236q-16 16-16 38 0 24 16 40 206 214 226 236z" horiz-adv-x="341" /> - -<glyph glyph-name="right-open" unicode="" d="M98 626l226-236q16-16 16-40 0-22-16-38l-226-236q-16-16-40-16t-40 16q-36 36 0 80l186 194-186 196q-36 44 0 80 16 16 41 16t39-16z" horiz-adv-x="340" /> - -<glyph glyph-name="up-open" unicode="" d="M564 280q16-16 16-41t-16-41q-38-38-78 0l-196 188-196-188q-40-38-78 0-16 16-16 41t16 41l234 224q16 16 40 16t40-16z" horiz-adv-x="580" /> - -<glyph glyph-name="down-open-mini" unicode="" d="M405 470q22 26 48 0 26-22 0-48l-196-192q-22-22-48 0l-196 192q-26 26 0 48 24 24 50 0l170-156z" horiz-adv-x="466" /> - -<glyph glyph-name="left-open-mini" unicode="" d="M252 180q26-26 0-48-26-26-48 0l-192 194q-24 24 0 50l192 194q22 26 48 0 26-22 0-48l-156-172z" horiz-adv-x="265" /> - -<glyph glyph-name="right-open-mini" unicode="" d="M13 180l158 170-158 172q-26 26 0 48 26 26 48 0l192-194q24-26 0-50l-192-194q-22-26-48 0-26 22 0 48z" horiz-adv-x="265" /> - -<glyph glyph-name="up-open-mini" unicode="" d="M62 230q-26-22-50 0-24 24 0 50l196 190q26 26 48 0l196-190q24-26 0-50-24-22-50 0l-170 158z" horiz-adv-x="464" /> - -<glyph glyph-name="down-open-big" unicode="" d="M63 570l370-356 372 356q22 26 48 0 26-22 0-48l-396-392q-22-22-48 0l-396 392q-26 26 0 48 24 24 50 0z" horiz-adv-x="866" /> - -<glyph glyph-name="left-open-big" unicode="" d="M452-20q26-26 0-48-26-26-48 0l-392 394q-24 24 0 50l392 394q22 26 48 0 26-22 0-48l-358-372z" horiz-adv-x="465" /> - -<glyph glyph-name="right-open-big" unicode="" d="M13-20l358 370-358 372q-26 26 0 48 26 26 48 0l392-394q24-26 0-50l-392-394q-22-26-48 0-26 22 0 48z" horiz-adv-x="465" /> - -<glyph glyph-name="up-open-big" unicode="" d="M804 130l-372 358-370-358q-26-22-50 0-24 24 0 50l396 390q26 26 48 0l396-390q24-26 0-50-26-22-48 0z" horiz-adv-x="864" /> - -<glyph glyph-name="down" unicode="" d="M660 366l-330-380-330 380 192 0 0 350 276 0 0-350 192 0z" horiz-adv-x="660" /> - -<glyph glyph-name="left" unicode="" d="M378 20l-378 330 378 330 0-190 352 0 0-278-352 0 0-192z" horiz-adv-x="730" /> - -<glyph glyph-name="right" unicode="" d="M350 680l380-330-380-330 0 192-350 0 0 278 350 0 0 190z" horiz-adv-x="730" /> - -<glyph glyph-name="up" unicode="" d="M660 336l-192 0 0-350-276 0 0 350-192 0 330 380z" horiz-adv-x="660" /> - -<glyph glyph-name="down-dir" unicode="" d="M460 550l-230-400-230 400 460 0z" horiz-adv-x="460" /> - -<glyph glyph-name="left-dir" unicode="" d="M400 580l0-460-400 230z" horiz-adv-x="400" /> - -<glyph glyph-name="right-dir" unicode="" d="M0 580l400-230-400-230 0 460z" horiz-adv-x="400" /> - -<glyph glyph-name="up-dir" unicode="" d="M0 150l230 400 230-400-460 0z" horiz-adv-x="460" /> - -<glyph glyph-name="down-bold" unicode="" d="M760 366l-380-380-380 380 192 0 0 350 376 0 0-350 192 0z" horiz-adv-x="760" /> - -<glyph glyph-name="left-bold" unicode="" d="M378 730l0-190 352 0 0-378-352 0 0-192-378 380z" horiz-adv-x="730" /> - -<glyph glyph-name="right-bold" unicode="" d="M350 730l380-380-380-380 0 192-350 0 0 378 350 0 0 190z" horiz-adv-x="730" /> - -<glyph glyph-name="up-bold" unicode="" d="M760 336l-192 0 0-350-376 0 0 350-192 0 380 380z" horiz-adv-x="760" /> - -<glyph glyph-name="down-thin" unicode="" d="M500 100l-250-240-250 240 162 0 0 740 176 0 0-740 162 0z" horiz-adv-x="500" /> - -<glyph glyph-name="left-thin" unicode="" d="M240 100l-240 250 240 250 0-160 740 0 0-178-740 0 0-162z" horiz-adv-x="980" /> - -<glyph glyph-name="right-thin" unicode="" d="M742 100l0 162-742 0 0 178 742 0 0 160 238-250z" horiz-adv-x="980" /> - -<glyph glyph-name="up-thin" unicode="" d="M500 602l-162 0 0-742-176 0 0 742-162 0 250 238z" horiz-adv-x="500" /> - -<glyph glyph-name="ccw" unicode="" d="M532 736q170 0 289-120t119-290-119-290-289-120q-142 0-252 88l70 74q84-60 182-60 126 0 216 90t90 218-90 218-216 90q-124 0-214-87t-92-211l142 0-184-204-184 204 124 0q2 166 122 283t286 117z" horiz-adv-x="940" /> - -<glyph glyph-name="cw" unicode="" d="M408 760q168 0 287-116t123-282l122 0-184-206-184 206 144 0q-4 124-94 210t-214 86q-126 0-216-90t-90-218q0-126 90-216t216-90q104 0 182 60l70-76q-110-88-252-88-168 0-288 120t-120 290 120 290 288 120z" horiz-adv-x="940" /> - -<glyph glyph-name="arrows-ccw" unicode="" d="M186 140l116 116 0-292-276 16 88 86q-116 122-114 290t120 288q100 100 240 116l4-102q-100-16-172-88-88-88-90-213t84-217z m332 598l276-16-88-86q116-122 114-290t-120-288q-96-98-240-118l-2 104q98 16 170 88 88 88 90 213t-84 217l-114-116z" horiz-adv-x="820" /> - -<glyph glyph-name="level-down" unicode="" d="M100 200q-42 0-71 30t-29 70l0 350 140 0 0-310 364 0 0 150 240-220-240-220 0 150-404 0z" horiz-adv-x="744" /> - -<glyph glyph-name="level-up" unicode="" d="M200 350l0-90-200 160 200 170 0-100 550 0q40 0 70-29t30-71l0-280-140 0 0 240-510 0z" horiz-adv-x="850" /> - -<glyph glyph-name="shuffle" unicode="" d="M754 516q-54 0-105-32t-80-66-83-104q-48-62-75-94t-78-77-107-66-122-21l-104 0 0 140 104 0q54 0 106 32t81 66 83 104q62 82 101 126t116 88 163 44l36 0 0 120 210-180-210-180 0 100-36 0z m-484-88q-74 78-166 78l-104 0 0 140 104 0q140 0 254-108-14-16-37-45t-27-33q-8-12-24-32z m520-242l0 100 210-180-210-180 0 120-36 0q-140 0-260 116 46 58 72 92 0 2 6 9t8 11q84-88 174-88l36 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="loop" unicode="" d="M800 540q42 0 71-29t29-71l0-290q0-40-29-70t-71-30l-700 0q-40 0-70 30t-30 70l0 290q0 42 30 71t70 29l250 0 0 110 200-180-200-180 0 110-210 0 0-210 620 0 0 210-150 0 0 140 190 0z" horiz-adv-x="900" /> - -<glyph glyph-name="switch" unicode="" d="M700 592l0-140-500 0 0-90-200 160 200 170 0-100 500 0z m300-420l-200-160 0 90-500 0 0 140 500 0 0 100z" horiz-adv-x="1000" /> - -<glyph glyph-name="play" unicode="" d="M486 376q14-10 14-26 0-14-14-24l-428-266q-24-16-41-6t-17 40l0 514q0 30 17 40t41-6z" horiz-adv-x="500" /> - -<glyph glyph-name="stop" unicode="" d="M526 650q74 0 74-64l0-470q0-66-74-66l-450 0q-76 0-76 66l0 470q0 36 18 50t58 14l450 0z" horiz-adv-x="600" /> - -<glyph glyph-name="pause" unicode="" d="M440 700q90 0 90-64l0-570q0-66-90-66t-90 66l0 570q0 64 90 64z m-350 0q90 0 90-64l0-570q0-66-90-66t-90 66l0 570q0 64 90 64z" horiz-adv-x="530" /> - -<glyph glyph-name="record" unicode="" d="M350 700q146 0 248-102t102-248q0-144-102-247t-248-103-248 103-102 247q0 146 102 248t248 102z" horiz-adv-x="700" /> - -<glyph glyph-name="to-end" unicode="" d="M412 374q14-10 14-24 0-12-14-22l-362-228q-22-14-36-5t-14 35l0 442q0 26 14 35t36-5z m114 268q74 0 74-58l0-466q0-58-74-58-76 0-76 58l0 466q0 58 76 58z" horiz-adv-x="600" /> - -<glyph glyph-name="to-start" unicode="" d="M174 350q0 14 14 24l364 228q20 14 34 5t14-35l0-442q0-26-14-35t-34 5l-364 228q-14 10-14 22z m-174 234q0 58 76 58 74 0 74-58l0-466q0-58-74-58-76 0-76 58l0 466z" horiz-adv-x="600" /> - -<glyph glyph-name="fast-forward" unicode="" d="M866 374q14-10 14-24t-14-22l-372-248q-22-14-37-6t-15 36l0 482q0 28 15 36t37-6z m-454 0q14-10 14-24t-14-22l-360-248q-20-14-36-6t-16 36l0 482q0 28 16 36t36-6z" horiz-adv-x="880" /> - -<glyph glyph-name="fast-backward" unicode="" d="M0 350q0 14 14 24l374 248q20 14 36 6t16-36l0-482q0-28-16-36t-36 6l-374 248q-14 8-14 22z m454 0q0 14 14 24l360 248q20 14 36 6t16-36l0-482q0-28-16-36t-36 6l-360 248q-14 8-14 22z" horiz-adv-x="880" /> - -<glyph glyph-name="progress-0" unicode="" d="M1000 450l0-250q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 300q0 40 30 70t70 30l800 0q42 0 71-30t29-70l0-50z m-100-250l0 300-800 0 0-300 800 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="progress-1" unicode="" d="M1000 450l0-250q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 300q0 40 30 70t70 30l800 0q42 0 71-30t29-70l0-50z m-100-250l0 300-800 0 0-300 800 0z m-750 50l0 198 200 0 0-198-200 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="progress-2" unicode="" d="M1000 450l0-250q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 300q0 40 30 70t70 30l800 0q42 0 71-30t29-70l0-50z m-100-250l0 300-800 0 0-300 800 0z m-750 50l0 198 200 0 0-198-200 0z m250 0l0 198 200 0 0-198-200 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="progress-3" unicode="" d="M1000 450l0-250q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 300q0 40 30 70t70 30l800 0q42 0 71-30t29-70l0-50z m-100-250l0 300-800 0 0-300 800 0z m-750 50l0 198 200 0 0-198-200 0z m250 0l0 198 200 0 0-198-200 0z m250 198l200 0 0-198-200 0 0 198z" horiz-adv-x="1000" /> - -<glyph glyph-name="target" unicode="" d="M430 780q178 0 304-126t126-304-126-304-304-126-304 126-126 304 126 304 304 126z m36-778q124 14 212 102t100 212l-192 0 0 70 192 0q-12 124-100 212t-212 102l0-194-70 0 0 194q-124-14-213-102t-101-212l194 0 0-70-194 0q12-124 101-212t213-102l0 194 70 0 0-194z" horiz-adv-x="860" /> - -<glyph glyph-name="list" unicode="" d="M100 200q20 0 35-15t15-35-15-35-35-15l-50 0q-20 0-35 15t-15 35 14 35 36 15l50 0z m0 200q20 0 35-15t15-35-15-35-35-15l-50 0q-20 0-35 15t-15 35 14 35 36 15l50 0z m0 200q20 0 35-15t15-35-15-35-35-15l-50 0q-20 0-35 15t-15 35 14 35 36 15l50 0z m200-100q-20 0-35 15t-15 35 15 35 35 15l350 0q22 0 36-15t14-35-15-35-35-15l-350 0z m350-100q22 0 36-15t14-35-15-35-35-15l-350 0q-20 0-35 15t-15 35 15 35 35 15l350 0z m0-200q22 0 36-15t14-35-15-35-35-15l-350 0q-20 0-35 15t-15 35 15 35 35 15l350 0z" horiz-adv-x="700" /> - -<glyph glyph-name="list-add" unicode="" d="M350 400q22 0 36-15t14-35-15-35-35-15l-300 0q-20 0-35 15t-15 35 14 35 36 15l300 0z m0-200q22 0 36-15t14-35-15-35-35-15l-300 0q-20 0-35 15t-15 35 14 35 36 15l300 0z m620 200q30 0 30-50t-30-50l-170 0 0-170q0-30-50-30t-50 30l0 170-164 0q-30 0-30 50t30 50l164 0 0 170q0 30 50 30t50-30l0-170 170 0z m-620 200q22 0 36-15t14-35-15-35-35-15l-300 0q-20 0-35 15t-15 35 14 35 36 15l300 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="battery" unicode="" d="M770 350q0-98 36-157t78-59l66 0q-30-46-64-65t-118-19l-500 0q-130 0-199 94t-69 206q0 110 69 205t199 95l500 0q84 0 118-19t64-65l-66 0q-42 0-78-60t-36-156z m-136-90q10 12-8 26-136 134-178 164-16 10-26 13t-18-5-10-12-8-18l-22-56-148 66q-26 12-34 0-8-14 8-28 136-132 180-162 34-16 42-11t18 31l24 58 146-68q26-12 34 2z m310 192q22 0 39-27t17-71-17-72-39-28l-38 0q-22 0-38 28t-16 72 16 71 38 27l38 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="back-in-time" unicode="" d="M532 760q170 0 289-120t119-290-119-290-289-120q-138 0-252 88l70 76q82-60 182-60 126 0 216 90t90 216q0 128-90 218t-216 90q-124 0-213-86t-93-210l142 0-184-206-184 206 124 0q4 166 123 282t285 116z m-36-190l70 0 0-204 130-130-50-50-150 150 0 234z" horiz-adv-x="940" /> - -<glyph glyph-name="monitor" unicode="" d="M900 790q42 0 71-30t29-70l0-550q0-42-29-77t-69-43l-218-44 86-38q50-28-20-28l-500 0q-98 0 32 52l36 14-220 44q-40 8-69 43t-29 77l0 550q0 40 30 70t70 30l800 0z m0-646l0 556-800 0 0-556 800 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="mobile" unicode="" d="M480 840q42 0 71-29t29-71l0-780q0-40-29-70t-71-30l-380 0q-40 0-70 30t-30 70l0 780q0 42 30 71t70 29l380 0z m-190-940q30 0 50 15t20 35q0 22-20 36t-50 14q-28 0-49-15t-21-35 21-35 49-15z m210 150l0 660-420 0 0-660 420 0z" horiz-adv-x="580" /> - -<glyph glyph-name="cd" unicode="" d="M460 810q190 0 325-135t135-325-135-325-325-135-325 135-135 325 135 325 325 135z m0-610q62 0 106 44t44 106q0 64-43 107t-107 43q-62 0-106-44t-44-106 44-106 106-44z" horiz-adv-x="920" /> - -<glyph glyph-name="inbox" unicode="" d="M967 398q40-42 30-72l-28-154q-4-20-22-33t-40-13l-816 0q-22 0-40 13t-22 33l-28 154q-8 32 32 72 8 10 36 38t68 67 52 51q22 22 52 22l516 0q30 0 52-22 16-16 53-52t67-65 38-39z m-266-32l178 0-102 114-556 0-102-114 178 0q8 0 12-8l40-100 300 0 40 100q4 8 12 8z" horiz-adv-x="999" /> - -<glyph glyph-name="install" unicode="" d="M884 306q24-52 14-96l-34-184q-2-20-19-35t-39-15l-712 0q-22 0-39 15t-19 35l-34 184q-8 50 14 96l158 374q22 46 72 46l104 0-20-204-134 0 254-210 256 210-136 0-18 204 102 0q50 0 74-46z m-68-132q2 22-10 38t-34 16l-644 0q-22 0-34-16t-10-38l14-74q2-22 19-37t37-15l592 0q22 0 39 15t19 37z" horiz-adv-x="901" /> - -<glyph glyph-name="globe" unicode="" d="M480 830q200 0 340-141t140-339q0-200-140-340t-340-140q-198 0-339 140t-141 340q0 198 141 339t339 141z m410-480q0 132-78 239t-202 149q-18-24-16-32 4-38 18-51t30-7l32 12t20 2q22-24 0-47t-45-56-1-77q34-64 96-64 28-2 43-36t17-66q10-80-14-140-22-44 14-76 86 112 86 250z m-466 404q-112-14-199-84t-127-174q6 0 22-2t28-3 26-4 24-8 12-13q4-12-14-45t-18-61q0-30 38-56t38-46q0-28 8-68t8-44q0-12 36-54t52-42q10 0 11 22t-2 54-3 40q0 32 14 74 12 42 59 70t55 46q16 34 9 61t-17 43-34 28-41 17-37 9-22 4q-16 6-42 7t-36-3-27 11-17 29q0 10 15 27t35 37 28 30q8 14 17 21t22 16 27 21q4 4 25 17t27 23z m-72-794q66-20 128-20 128 0 226 68-26 44-118 34-24-2-65-17t-47-17q-74-16-76-16-12-2-26-14t-22-18z" horiz-adv-x="960" /> - -<glyph glyph-name="cloud" unicode="" d="M760 494q100 0 170-68t70-166-70-166-170-68l-578 0q-74 0-128 52t-54 124q0 74 53 126t129 52q2 0 10-1t10-1q-2 12-2 38 0 108 78 184t188 76q90 0 160-52t94-134q28 4 40 4z" horiz-adv-x="1000" /> - -<glyph glyph-name="cloud-thunder" unicode="" d="M760 494q100 0 170-68t70-166-70-166-170-68l-578 0q-74 0-128 52t-54 124q0 74 53 126t129 52q2 0 10-1t10-1q-2 12-2 38 0 108 78 184t188 76q90 0 160-52t94-134q28 4 40 4z m-192-216q14 16 14 30 0 20-30 32l-4 0q-26 14-38 16l50 116q6 0 6 20 0 14-8 18-16 10-34-8-2-2-30-32t-61-66-45-52q-12-18-12-30 0-22 30-30l4-2q8-4 38-16l-52-114-2-8q-2-8-2-14 0-10 8-18 18-10 34 10 100 100 134 148z" horiz-adv-x="1000" /> - -<glyph glyph-name="flash" unicode="" d="M40-100q-4 4 35 94t79 182 38 98-94 45-98 55q-4 12 84 120t180 209 96 97q6-4-74-186t-78-186 95-43 97-57q4-20-174-227t-186-201z" horiz-adv-x="400" /> - -<glyph glyph-name="moon" unicode="" d="M524 238q106 106 125 252t-53 270q52-26 96-72 128-128 128-309t-128-309-310-128-310 128q-40 40-72 94 124-70 271-51t253 125z" horiz-adv-x="820" /> - -<glyph glyph-name="flight" unicode="" d="M268-120l124 400-180 0-112-100-100 0 80 170-80 170 100 0 112-100 180 0-124 400 100 0 224-400 274 0t36-4 46-11 36-21 16-34q0-32-38-49t-74-19l-38-2-258 0-224-400-100 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="paper-plane" unicode="" d="M894 720q14 4 22-3t4-19q-2-6-72-310t-74-316q-2-14-14-19t-24 1l-248 134-30 16 22 26q388 420 394 426 4 4-1 9t-9 1l-550-402-112 44-190 76q-12 4-12 12t12 12q8 4 441 157t441 155z m-582-728l0 204 160-82q-130-116-142-128-18-14-18 6z" horiz-adv-x="921" /> - -<glyph glyph-name="leaf" unicode="" d="M236 646q182 106 506 66 168-22 196-50 4-6-2-10-76-40-130-109t-78-132-65-132-93-105q-138-96-382-4-66-76-114-176-12-24-47-7t-25 39q44 100 129 193t176 153 176 106 141 68l54 20q-14 0-41-1t-104-14-148-38-162-84-161-141q-22 242 174 358z" horiz-adv-x="940" /> - -<glyph glyph-name="lifebuoy" unicode="" d="M454 810q190 2 326-130t140-322q2-190-131-327t-323-141q-190-2-327 131t-139 323q-4 190 130 327t324 139z m0-60q-94 0-178-44l62-104q56 28 122 28t122-28l62 104q-88 46-190 44z m-246-522q-28 60-28 122 0 64 28 124l-102 62q-46-88-46-190 2-96 46-180z m258-278q98 4 178 46l-62 104q-60-30-122-30t-122 30l-62-104q86-46 190-46z m-6 180q92 0 156 65t64 155q0 92-64 156t-156 64-156-64-64-156q0-90 64-155t156-65z m252 98l104-62q46 96 44 190 0 96-44 180l-104-62q28-60 28-124 0-62-28-122z" horiz-adv-x="920" /> - -<glyph glyph-name="mouse" unicode="" d="M551 130q28-80-17-157t-139-111q-94-28-175 9t-103 117l-106 384q-20 68 6 134t84 106l-96 186q-14 34 14 48 30 18 48-14l98-192q80 22 154-16t102-116z m-324 274q28 10 40 36t4 54q-10 28-35 41t-53 5q-28-10-40-36t-4-54q10-28 35-41t53-5z" horiz-adv-x="561" /> - -<glyph glyph-name="briefcase" unicode="" d="M456 326l0-100-456 0q8 226 10 292 4 108 100 108l160 0q16 26 37 67t23 45q14 26 23 32t37 6l222 0q26 0 36-7t22-31q18-32 60-112l160 0q96 0 100-108l10-292-454 0 0 100-90 0z m-74 354l-28-54 292 0-28 54q-14 26-42 26l-152 0q-28 0-42-26z m164-604l0 100 430 0q-6-88-10-166-6-84-90-84l-750 0q-90 0-90 84l-10 166 430 0 0-100 90 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="suitcase" unicode="" d="M900 650q42 0 71-30t29-70l0-550q0-42-29-71t-71-29l-50 0 0 750 50 0z m-900-100q0 40 30 70t70 30l50 0 0-750-50 0q-40 0-70 29t-30 71l0 550z m670 204l0-104 110 0 0-750-560 0 0 750 110 0 0 104q98 46 170 46t170-46z m-60-104l0 66q-52 24-110 24-54 0-110-24l0-66 220 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="dot" unicode="" d="M110 460q46 0 78-32t32-78q0-44-32-77t-78-33-78 33-32 77q0 46 32 78t78 32z" horiz-adv-x="220" /> - -<glyph glyph-name="dot-2" unicode="" d="M110 460q46 0 78-32t32-78q0-44-32-77t-78-33-78 32-32 78 32 78 78 32z m350 0q46 0 78-32t32-78q0-44-33-77t-77-33q-46 0-78 32t-32 78 32 78 78 32z" horiz-adv-x="570" /> - -<glyph glyph-name="dot-3" unicode="" d="M110 460q46 0 78-32t32-78q0-44-32-77t-78-33-78 33-32 77q0 46 32 78t78 32z m350 0q46 0 78-32t32-78q0-44-33-77t-77-33-77 33-33 77q0 46 32 78t78 32z m350 0q46 0 78-32t32-78q0-44-32-77t-78-33-78 33-32 77q0 46 32 78t78 32z" horiz-adv-x="920" /> - -<glyph glyph-name="brush" unicode="" d="M118 170q38 34 85 29t87-45q42-40 48-87t-30-83q-86-84-228-102-84-12-80 14 0 4 6 10 52 60 64 145t48 119z m840 646q26-26-148-248t-292-338q-38-38-124-104-8-6-16 8-18 34-48 64-32 32-66 48-16 6-8 16 64 84 104 122 118 116 344 287t254 145z" horiz-adv-x="962" /> - -<glyph glyph-name="infinity" unicode="" d="M796 570q84 0 144-53t60-167q0-112-60-166t-144-54q-78 0-157 40t-139 106q-58-66-137-106t-157-40q-86 0-146 54t-60 166q0 114 60 167t146 53q78 0 157-39t137-105q58 66 138 105t158 39z m-590-352q60 0 127 37t113 95q-46 58-112 95t-128 37q-114 0-114-132t114-132z m590 0q114 0 114 132t-114 132q-62 0-129-37t-111-95q44-58 111-95t129-37z" horiz-adv-x="1000" /> - -<glyph glyph-name="erase" unicode="" d="M902 700q42 0 71-29t29-71l0-500q0-40-29-70t-71-30l-478 0q-38 0-70 28l-340 296q-28 26 0 54l340 296q30 26 70 26l478 0z m-140-550l72 74-128 126 128 128-72 72-128-126-128 126-72-72 128-128-128-126 72-74 128 128z" horiz-adv-x="1002" /> - -<glyph glyph-name="chart-pie" unicode="" d="M368 770l0-368-368 0q18 146 121 249t247 119z m106 0q156-20 261-139t105-279q0-174-123-298t-299-124q-160 0-278 105t-140 263l424 0q20 0 35 14t15 36l0 422z" horiz-adv-x="840" /> - -<glyph glyph-name="chart-line" unicode="" d="M34 284q-42 10-32 56 10 42 54 32l98-24-52-80z m890-12q14 12 33 11t31-15q32-32-2-64l-252-226q-12-12-30-12-14 0-28 10l-286 220-54 14 50 80 36-8q12-4 16-8l264-204z m-490 220l-350-550q-12-22-38-22-12 0-24 8-16 10-20 29t6 33l374 588q8 16 28 20 18 6 36-6l246-156 226 326q10 16 28 19t34-9q38-24 12-62l-252-362q-24-36-62-12z" horiz-adv-x="1003" /> - -<glyph glyph-name="chart-bar" unicode="" d="M750 800q22 0 36-15t14-35l0-850-200 0 0 850q0 50 40 50l110 0z m-300-300q22 0 36-15t14-35l0-550-200 0 0 550q0 50 40 50l110 0z m-300-300q22 0 36-15t14-35l0-250-200 0 0 250q0 50 40 50l110 0z" horiz-adv-x="800" /> - -<glyph glyph-name="chart-area" unicode="" d="M964 732q16 22 16-4l0-768-964 0q-12 0-15 7t5 17l230 288q20 22 40 2l74-66q10-8 21-7t17 11l158 238q16 26 38 4l112-104q20-20 38 4z" horiz-adv-x="980" /> - -<glyph glyph-name="tape" unicode="" d="M770 580q96 0 163-67t67-163q0-94-67-162t-163-68l-540 0q-94 0-162 68t-68 162q0 96 68 163t162 67q96 0 163-67t67-163q0-72-40-130l160 0q-40 64-40 130 0 96 68 163t162 67z m-670-230q0-52 38-91t92-39 92 39 38 91q0 54-38 92t-92 38-92-38-38-92z m670-130q54 0 92 39t38 91q0 54-38 92t-92 38-92-38-38-92q0-52 38-91t92-39z" horiz-adv-x="1000" /> - -<glyph glyph-name="graduation-cap" unicode="" d="M166 238l334-168 276 136q-4-22-8-47t-6-35-11-23-24-23-45-22q-40-18-80-41t-63-34-39-11-40 13-64 37-80 40q-72 32-103 69t-47 109z m810 246q24-14 24-33t-24-33l-78-44-308 102q-22 36-90 36-40 0-67-16t-27-40 27-40 67-16q26 0 36 4l292-68-268-152q-60-32-120 0l-416 234q-24 14-24 33t24 33l416 234q60 32 120 0z m-128-442q18 116 13 182t-19 90l-14 22 70 38q6-8 12-28t17-101-7-197q-4-26-22-30t-35 5-15 19z" horiz-adv-x="1000" /> - -<glyph glyph-name="language" unicode="" d="M988 306q30-82-10-176t-134-160q-10 0-12 2t-16 19-16 19q-2 6 2 10 86 60 117 152t-11 148q-16-38-39-76t-59-80-86-65-106-15q-52 6-84 41t-32 93q0 84 60 148 50 50 114 66l-2 100q-140-24-146-24-6-2-10 4 0 2-5 29t-5 31q-2 2 1 4t7 2l156 28q0 110-2 114 0 8 8 8 46 0 52 2 10 0 10-8l0-104q158 22 164 22 8 4 10-6 0-2 4-23t4-25q4-10-4-12l-176-30 0-102 12 0q86 0 148-36t86-100z m-370-160q28-6 62 6l-4 214q-34-12-60-40-44-44-44-108 0-66 46-72z m122 28q28 24 58 68t45 79 7 41q-36 18-96 18-2 0-6-1t-6-1z m-448 382q10-28 53-165t83-261 40-126q0-4-4-4l-86 0q-6 0-6 4l-50 166-176 0q-48-164-50-166 0-4-6-4l-86 0q-4 0-4 4 10 18 176 552 2 8 10 8l96 0q10 0 10-8z m-130-316l144 0-72 264z" horiz-adv-x="1001" /> - -<glyph glyph-name="ticket" unicode="" d="M216 272l326 326 178-178-326-326z m710 244q14-14 14-36t-14-36l-550-550q-16-16-36-16t-36 16l-76 76q12 20 12 48 0 42-29 72t-71 30q-22 0-50-14l-74 76q-16 16-16 36t16 36l550 550q14 14 36 14t36-14l74-76q-12-22-12-48 0-42 30-71t72-29q26 0 48 12z m-532-502l406 406-258 258-408-406z" horiz-adv-x="940" /> - -<glyph glyph-name="water" unicode="" d="M168 844q10-86 50-155t73-123 33-112q0-66-48-113t-114-47-114 47-48 113q0 58 33 112t73 123 50 155q2 4 7 4t5-4z m616 0q10-86 50-155t73-123 33-112q0-66-48-113t-114-47-114 47-48 113q0 48 21 93t48 78 53 92 34 127q2 4 7 4t5-4z m-320-444q2 4 7 4t5-4q10-86 50-155t73-123 33-112q0-66-48-113t-114-47-114 47-48 113q0 58 33 112t73 123 50 155z" horiz-adv-x="940" /> - -<glyph glyph-name="droplet" unicode="" d="M290 822q14-118 60-219t92-159 82-136 36-160q0-114-83-196t-197-82-197 82-83 196q0 82 36 160t82 136 92 159 60 219q2 8 11 8t9-8z m-42-392q2 4-2 14-6 6-14 6t-12-6l-40-58q-32-46-48-70t-34-75-18-101q0-24 17-41t41-17q58 0 58 68 0 94 42 246 2 6 5 17t5 17z" horiz-adv-x="560" /> - -<glyph glyph-name="air" unicode="" d="M85 534q-16-14-36-12t-34 18q-14 14-12 36t18 36q48 40 79 60t89 40 129 4 159-66 155-53 100 16 89 67q38 30 70-6 32-40-6-72-122-110-234-110-100 0-222 70-68 38-119 52t-93 0-65-29-67-51z m736-110q38 32 70-6 32-40-6-72-40-34-65-53t-72-38-97-19q-96 0-222 70-68 38-119 52t-93 0-65-29-67-51q-14-14-35-12t-35 18q-32 40 6 72 38 34 60 50t69 38 88 23 105-15 134-56q68-38 119-52t93 0 65 29 67 51z m0-256q38 32 70-6 14-14 12-36t-18-36q-40-34-65-53t-72-38-97-19q-96 0-222 70-68 38-119 52t-93 1-66-29-66-52q-14-14-35-12t-35 18q-32 40 6 72 38 34 60 50t69 38 88 23 105-15 134-56q68-38 119-52t93 0 65 29 67 51z" horiz-adv-x="905" /> - -<glyph glyph-name="credit-card" unicode="" d="M900 700q42 0 71-30t29-70l0-500q0-42-29-71t-71-29l-800 0q-40 0-70 29t-30 71l0 500q0 40 30 70t70 30l800 0z m0-600l0 300-800 0 0-300 800 0z m0 450l0 50-800 0 0-50 800 0z m-700-256l30 0 0-30-30 0 0 30z m180-60l30 0 0 30 30 0 0 30 60 0 0-30-30 0 0-30-30 0 0-30-60 0 0 30z m120-30l-30 0 0 30 30 0 0-30z m-150 0l-60 0 0 30 60 0 0-30z m30 60l0-30-30 0 0 60 60 0 0-30-30 0z m-120-30l0-30-60 0 0 30 30 0 0 30 30 0 0 30 60 0 0-30-30 0 0-30-30 0z" horiz-adv-x="1000" /> - -<glyph glyph-name="floppy" unicode="" d="M658 750l142-156 0-544q0-40-29-70t-71-30l-600 0q-40 0-70 30t-30 70l0 600q0 42 30 71t70 29l558 0z m-58-300l0 250-400 0 0-250q0-20 15-35t35-15l300 0q20 0 35 15t15 35z m-50 200l0-200-100 0 0 200 100 0z" horiz-adv-x="800" /> - -<glyph glyph-name="clipboard" unicode="" d="M630 750q28 0 49-21t21-49l0-760q0-30-21-50t-49-20l-560 0q-28 0-49 20t-21 50l0 760q0 28 21 49t49 21l60-150 440 0z m-100-100l-360 0-44 100 108 0 36 100 160 0 36-100 110 0z" horiz-adv-x="700" /> - -<glyph glyph-name="megaphone" unicode="" d="M792 500q58-138 67-258t-39-140q-28-12-61 3t-65 40-99 41-149 8q-28-4-42-19t-6-37q22-56 46-108 4-10 24-22t24-20q14-34-22-46-50-22-102-40-30-10-54 42-32 76-58 132-6 12-34 17t-46 31q-30-10-38-14-34-12-74 12t-54 60q-17 32-5 79t43 61q126 52 213 108t124 103 59 92 25 78 15 59 36 36q48 20 130-70t142-228z m-28-300q8 4 10 38t-11 98-41 128q-28 66-67 123t-67 84-36 23-10-42 10-105 40-133 68-119 68-76 36-19z" horiz-adv-x="860" /> - -<glyph glyph-name="database" unicode="" d="M686 208q14 20 14-2l0-100q0-74-104-135t-246-61q-140 0-245 61t-105 135l0 100q0 8 4 10t10-8q32-52 125-86t211-34 211 34 125 86z m2 254q8 16 12 0l0-116q0-68-102-114t-248-46q-144 0-247 46t-103 114l0 116q0 20 14 0 30-46 124-75t212-29 212 29 126 75z m-338 328q144 0 247-39t103-93l0-64q0-58-103-99t-247-41-247 41-103 99l0 64q0 54 103 93t247 39z" horiz-adv-x="700" /> - -<glyph glyph-name="drive" unicode="" d="M884 304q26-44 14-96l-34-184q-2-20-19-35t-39-15l-712 0q-20 0-38 15t-20 35l-34 184q-8 52 14 96l158 374q22 46 72 46l408 0q50 0 74-46z m-68-132q2 22-10 38t-34 16l-644 0q-22 0-34-16t-10-38l14-74q2-22 19-37t39-15l590 0q22 0 39 15t19 37z" horiz-adv-x="902" /> - -<glyph glyph-name="bucket" unicode="" d="M522 780q174 0 286-49t104-105q-6-38-48-307t-44-281q-2-18-37-44t-107-50-154-24-153 24-106 50-37 44q0 2-4 30 82-6 163 35t139 117q28 0 48 20t20 50q0 28-20 49t-50 21q-28 0-49-21t-21-49q0-20 10-36-48-58-115-89t-131-27q-102 10-157 57t-59 109q-8 122 156 184-18 94-22 138-8 56 104 105t284 49z m-452-470q4-32 37-59t91-39l-32 204q-100-44-96-106z m452 212q82 0 157 18t113 39 38 35-38 35-112 39-158 18q-82 0-156-18t-112-39-38-35 38-35 112-39 156-18z" horiz-adv-x="913" /> - -<glyph glyph-name="thermometer" unicode="" d="M400 356q64-36 102-98t38-138q0-112-79-191t-191-79-191 79-79 191q0 76 38 138t102 98l0 444q0 50 40 50l170 0q20 0 35-15t15-35l0-444z m-130-406q70 0 120 50t50 120q0 56-32 100t-84 60l0 370-100 0 0-368q-54-16-89-61t-35-101q0-70 50-120t120-50z" horiz-adv-x="540" /> - -<glyph glyph-name="key" unicode="" d="M774 612q20-116-28-215t-150-117q-66-12-130-2l-118-194-70-12-104-166q-14-28-46-32l-76-14q-12-4-22 4t-12 22l-16 98q-8 30 12 56l258 386q-24 50-38 120-18 106 53 187t185 101q106 20 195-45t107-177z m-126-76q30 44 21 97t-51 83q-42 32-92 22t-80-54q-8-12-12-23t-1-20 5-16 13-17 18-15 22-16 23-17q6-4 22-16t23-16 19-12 19-8 17 1 18 8 16 19z" horiz-adv-x="780" /> - -<glyph glyph-name="flow-cascade" unicode="" d="M520 120q50 0 85-35t35-85-35-85-85-35q-80 0-110 74l-164 0q-88 0-131 54t-43 118l0 464q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-114q0-78 78-78l164 0q30 72 110 72 50 0 85-35t35-85-35-85-85-35q-80 0-110 74l-164 0q-42 0-78 16l0-194q0-78 78-78l164 0q30 72 110 72z m0 300q-28 0-49-20t-21-50q0-28 21-48t49-20 49 20 21 48q0 30-21 50t-49 20z m-470 280q0-28 21-48t49-20 49 20 21 48q0 30-21 50t-49 20-49-20-21-50z m470-768q28 0 49 20t21 48q0 30-21 50t-49 20-49-20-21-50q0-28 21-48t49-20z" horiz-adv-x="640" /> - -<glyph glyph-name="flow-branch" unicode="" d="M640 650q0-80-74-110-6-58-28-101t-61-69-68-38-75-26q-42-14-63-22t-47-24-38-40-16-60q70-30 70-110 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 378q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-204q40 30 138 60 58 18 84 29t51 41 29 76q-70 32-70 108 0 50 35 85t85 35 85-35 35-85z m-588 0q0-28 20-48t48-20 49 20 21 48q0 30-21 50t-49 20-48-20-20-50z m68-668q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z m400 600q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z" horiz-adv-x="640" /> - -<glyph glyph-name="flow-tree" unicode="" d="M868 112q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 114q0 78-76 78l-100 0q-44 0-78 12l0-204q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 204q-30-12-76-12l-100 0q-34 0-53-19t-22-33-3-26l0-114q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 114q0 64 43 118t131 54l100 0q76 0 76 52l0 140q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-140q0-52 78-52l100 0q86 0 129-54t43-118l0-114z m-678-112q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20 49 20 21 48z m212 700q0-28 20-48t48-20 49 20 21 48q0 30-21 50t-49 20-48-20-20-50z m138-700q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20 49 20 21 48z m280-68q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z" horiz-adv-x="940" /> - -<glyph glyph-name="flow-line" unicode="" d="M168 162q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 378q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-378z m-116 488q0-28 20-48t48-20 49 20 21 48q0 30-21 50t-49 20-48-20-20-50z m68-668q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z" horiz-adv-x="240" /> - -<glyph glyph-name="flow-parallel" unicode="" d="M240 650q0-76-72-110l0-378q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 378q-72 34-72 110 0 50 35 85t85 35 85-35 35-85z m-50-600q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20 49 20 21 48z m-70 532q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z m448-420q72-34 72-112 0-50-35-85t-85-35-85 35-35 85q0 78 72 112l0 378q-72 34-72 110 0 50 35 85t85 35 85-35 35-85q0-76-72-110l0-378z m-116 488q0-28 20-48t48-20 49 20 21 48q0 30-21 50t-49 20-48-20-20-50z m68-668q28 0 49 20t21 48q0 30-21 50t-49 20-48-20-20-50q0-28 20-48t48-20z" horiz-adv-x="640" /> - -<glyph glyph-name="rocket" unicode="" d="M543 236q6-50 8-81t-8-59-13-40-35-32-45-26-70-31-85-37q-32-12-45 4t-3 44l40 110-130 132-106-40q-28-12-43 2t-3 46q12 30 31 79t27 65 22 45 25 36 29 20 41 13l52 0t71-6q10 14 29 39t77 85 118 104 145 75 165 19q8 0 14-6 4-4 6-14 10-82-18-168t-76-151-98-118-86-81z m50 296q22-22 54-22t54 22q22 24 22 56t-22 56q-22 22-54 22t-54-22q-22-24-22-56t22-56z" horiz-adv-x="860" /> - -<glyph glyph-name="gauge" unicode="" d="M406 178q34 56 214 284t194 220q12-6-96-278t-138-326q-50-86-136-36t-38 136z m94 380q-168 0-284-127t-116-311q0-30 2-46 2-22-12-37t-34-17-36 12-18 34q0 8-1 26t-1 28q0 226 145 382t355 156q72 0 134-18l-70-86q-40 4-64 4z m362-62q138-154 138-376 0-38-2-56-2-20-16-33t-34-13l-4 0q-22 4-35 20t-11 36q2 14 2 46 0 150-80 268 6 14 20 51t22 57z" horiz-adv-x="1000" /> -</font> -</defs> -</svg> \ No newline at end of file diff --git a/src/mol-app/skin/fonts/fontello.ttf b/src/mol-app/skin/fonts/fontello.ttf deleted file mode 100644 index 39a234370e14bbf53e699758840b2ea5de8ccede..0000000000000000000000000000000000000000 Binary files a/src/mol-app/skin/fonts/fontello.ttf and /dev/null differ diff --git a/src/mol-app/skin/fonts/fontello.woff b/src/mol-app/skin/fonts/fontello.woff deleted file mode 100644 index 674807bae0bb1793ab6274a50737b707d9356fd2..0000000000000000000000000000000000000000 Binary files a/src/mol-app/skin/fonts/fontello.woff and /dev/null differ diff --git a/src/mol-app/skin/fonts/fontello.woff2 b/src/mol-app/skin/fonts/fontello.woff2 deleted file mode 100644 index 49eb9640642432843920fcacac3346c95157ba26..0000000000000000000000000000000000000000 Binary files a/src/mol-app/skin/fonts/fontello.woff2 and /dev/null differ diff --git a/src/mol-app/skin/icons.scss b/src/mol-app/skin/icons.scss deleted file mode 100644 index 3d1d6cfcbee2d44a08ac532caf8aedc1725326b4..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/icons.scss +++ /dev/null @@ -1,135 +0,0 @@ - -[class^="molstar-icon-"]:before, [class*=" molstar-icon-"]:before { - font-family: "fontello"; - font-style: normal; - font-weight: normal; - speak: none; - - display: inline-block; - text-decoration: inherit; - width: 1em; - margin-right: .2em; - text-align: center; - /* opacity: .8; */ - - /* For safety - reset parent styles, that can break glyph codes*/ - font-variant: normal; - text-transform: none; - - /* fix buttons height, for twitter bootstrap */ - line-height: 1em; - - /* Animation center compensation - margins should be symmetric */ - /* remove if not needed */ - margin-left: .2em; - - /* you can be more comfortable with increased icons size */ - /* font-size: 120%; */ - - /* Font smoothing. That was taken from TWBS */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - /* Uncomment for 3D effect */ - /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ - } - - .molstar-icon-expand-layout:before { - content: "\e84a"; - } - - .molstar-icon-plus:before { - content: "\e816"; - } - - .molstar-icon-minus:before { - content: "\e819"; - } - - .molstar-icon-reset-scene:before { - content: "\e891"; - } - - .molstar-icon-ok:before { - content: "\e812"; - } - - .molstar-icon-cross:before { - content: "\e868"; - } - - .molstar-icon-off:before { - content: "\e813"; - } - - .molstar-icon-expand:before { - content: "\e885"; - } - - .molstar-icon-collapse:before { - content: "\e883"; - } - - .molstar-icon-visual-visibility:before { - content: "\e826"; - } - - .molstar-icon-abort:before { - content: "\e814"; - } - - .molstar-icon-focus-on-visual:before { - content: "\e8a3"; - } - - .molstar-icon-settings:before { - content: "\e855"; - } - - .molstar-icon-tools:before { - content: "\e856"; - } - - .molstar-icon-log:before { - content: "\e8a5"; - } - - .molstar-icon-remove:before { - content: "\e847"; - } - - .molstar-icon-help:before { - content: '\e81c' - } - - .molstar-icon-info:before { - content: '\e81e' - } - - .molstar-icon-left-open-big:before { - content: '\e87c' - } - - .molstar-icon-right-open-big:before { - content: '\e87d' - } - - .molstar-icon-left-open:before { - content: '\e874' - } - - .molstar-icon-right-open:before { - content: '\e875' - } - - .molstar-icon-screenshot:before { - content: "\e80f"; - } - - .molstar-icon-help:before { - content: "\e81c"; - } - - .molstar-icon-help-circle:before { - content: "\e81d"; - } \ No newline at end of file diff --git a/src/mol-app/skin/layout.scss b/src/mol-app/skin/layout.scss deleted file mode 100644 index ded62b22132c4b64ff0b276f2523b5b9b377b282..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/layout.scss +++ /dev/null @@ -1,29 +0,0 @@ - -@import 'layout/common'; - -.molstar-layout-standard-outside { - position: absolute; - @import 'layout/outside'; -} - -.molstar-layout-standard-landscape { - position: absolute; - @import 'layout/landscape'; -} - -.molstar-layout-standard-portrait { - position: absolute; - @import 'layout/portrait'; -} - -.molstar-layout-expanded { - position: fixed; - - @media (orientation:landscape) { - @import 'layout/landscape'; - }; - - @media (orientation:portrait) { - @import 'layout/portrait'; - }; -} \ No newline at end of file diff --git a/src/mol-app/skin/layout/common.scss b/src/mol-app/skin/layout/common.scss deleted file mode 100644 index 219de13b1086c2c6ecd7d3ac1d27b5007b1e97c8..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/layout/common.scss +++ /dev/null @@ -1,60 +0,0 @@ - -.molstar-layout-expanded, .molstar-layout-standard { - left: 0; - right: 0; - top: 0; - bottom: 0; -} - -.molstar-layout-region { - overflow: hidden; - background: $default-background; -} - -.molstar-layout-static, .molstar-layout-scrollable { - position: absolute; -} - -.molstar-layout-scrollable { - overflow-y: auto; -} - -.molstar-layout-static { - overflow: hidden; -} - -.molstar-layout-main, .molstar-layout-bottom, .molstar-layout-top { - .molstar-layout-static { - left: 0; - right: 0; - top: 0; - bottom: 0; - } -} - -.molstar-layout-right { - - .molstar-layout-static { - left: 0; - right: 0; - top: 0; - height: $row-height + $control-spacing; - } - - .molstar-layout-scrollable { - left: 0; - right: 0; - top: $row-height + $control-spacing + 1; - bottom: 0; - } - -} - -.molstar-layout-left { - .molstar-layout-static { - left: 0; - right: 0; - bottom: 0; - top: 0; - } -} \ No newline at end of file diff --git a/src/mol-app/skin/layout/landscape.scss b/src/mol-app/skin/layout/landscape.scss deleted file mode 100644 index 418a7cd4bc0a35f244cc1ce59123527ff679e0d4..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/layout/landscape.scss +++ /dev/null @@ -1,81 +0,0 @@ - -.molstar-layout-main { - position: absolute; - left: $expanded-left-width; - right: $expanded-right-width; - bottom: $expanded-bottom-height; - top: $expanded-top-height; -} - -.molstar-layout-top { - position: absolute; - left: $expanded-left-width; - right: $expanded-right-width; - height: $expanded-top-height; - top: 0; - border-bottom: 1px solid $border-color; -} - -.molstar-layout-bottom { - position: absolute; - left: $expanded-left-width; - right: $expanded-right-width; - height: $expanded-bottom-height; - bottom: 0; - border-top: 1px solid $border-color; -} - -.molstar-layout-right { - position: absolute; - width: $expanded-right-width; - right: 0; - bottom: 0; - top: 0; - border-left: 1px solid $border-color; -} - -.molstar-layout-left { - position: absolute; - width: $expanded-left-width; - left: 0; - bottom: 0; - top: 0; - border-right: 1px solid $border-color; -} - -.molstar-layout-hide-right { - .molstar-layout-right { - display: none; - } - .molstar-layout-main, .molstar-layout-top, .molstar-layout-bottom { - right: 0; - } -} - - -.molstar-layout-hide-left { - .molstar-layout-left { - display: none; - } - .molstar-layout-main, .molstar-layout-top, .molstar-layout-bottom { - left: 0; - } -} - -.molstar-layout-hide-bottom { - .molstar-layout-bottom { - display: none; - } - .molstar-layout-main { - bottom: 0; - } -} - -.molstar-layout-hide-top { - .molstar-layout-top { - display: none; - } - .molstar-layout-main { - top: 0; - } -} \ No newline at end of file diff --git a/src/mol-app/skin/layout/outside.scss b/src/mol-app/skin/layout/outside.scss deleted file mode 100644 index 74cac3e423634f96522cec4efa20b69e8a9a56e5..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/layout/outside.scss +++ /dev/null @@ -1,89 +0,0 @@ - -.molstar-layout-main { - position: absolute; - left: 0; - right: 0; - bottom: 0; - top: 0; -} - -.molstar-layout-top { - position: absolute; - right: 0; - height: $standard-top-height; - top: -$standard-top-height; - width: 50%; - border-left: 1px solid $border-color; - border-bottom: 1px solid $border-color; -} - -.molstar-layout-bottom { - position: absolute; - left: 0; - right: 0; - height: $standard-top-height; - top: -$standard-top-height; - width: 50%; - border-bottom: 1px solid $border-color; -} - -.molstar-layout-right { - position: absolute; - width: 50%; - right: 0; - bottom: -$standard-bottom-height; - height: $standard-bottom-height; - border-left: 1px solid $border-color; - border-top: 1px solid $border-color; -} - -.molstar-layout-left { - position: absolute; - width: 50%; - left: 0; - bottom: 0; - bottom: -$standard-bottom-height; - height: $standard-bottom-height; - border-top: 1px solid $border-color; -} - -///////////////////////////////////////// -.molstar-layout-hide-right { - .molstar-layout-right { - display: none; - } - .molstar-layout-left { - width: 100%; - } -} - -.molstar-layout-hide-left { - .molstar-layout-left { - display: none; - } - .molstar-layout-right { - width: 100%; - border-left: none; - } -} - -/////////////////////////////////// -.molstar-layout-hide-top { - .molstar-layout-top { - display: none; - } - .molstar-layout-bottom { - width: 100%; - border-left: none; - } -} - -.molstar-layout-hide-bottom { - .molstar-layout-bottom { - display: none; - } - .molstar-layout-top { - width: 100%; - border-left: none; - } -} \ No newline at end of file diff --git a/src/mol-app/skin/layout/portrait.scss b/src/mol-app/skin/layout/portrait.scss deleted file mode 100644 index efaf39113d637f9e5b18cf67092274c024c07393..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/layout/portrait.scss +++ /dev/null @@ -1,99 +0,0 @@ - -.molstar-layout-main { - position: absolute; - left: 0; - right: 0; - bottom: $expanded-portrait-bottom-height; - top: $expanded-portrait-top-height; -} - -.molstar-layout-top { - position: absolute; - right: 0; - height: $expanded-portrait-top-height; - top: 0; - width: 50%; - border-left: 1px solid $border-color; - border-bottom: 1px solid $border-color; -} - -.molstar-layout-bottom { - position: absolute; - left: 0; - right: 0; - height: $expanded-portrait-top-height; - width: 50%; - border-bottom: 1px solid $border-color; -} - -.molstar-layout-right { - position: absolute; - width: 50%; - right: 0; - bottom: 0; - height: $expanded-portrait-bottom-height; - border-left: 1px solid $border-color; - border-top: 1px solid $border-color; -} - -.molstar-layout-left { - position: absolute; - width: 50%; - left: 0; - bottom: 0; - height: $expanded-portrait-bottom-height; - border-top: 1px solid $border-color; -} - -///////////////////////////////////////// -.molstar-layout-hide-right { - .molstar-layout-right { - display: none; - } - .molstar-layout-left { - width: 100%; - } -} - -.molstar-layout-hide-left { - .molstar-layout-left { - display: none; - } - .molstar-layout-right { - width: 100%; - border-left: none; - } -} - -.molstar-layout-hide-right.molstar-layout-hide-left { - .molstar-layout-main { - bottom: 0; - } -} - -/////////////////////////////////// -.molstar-layout-hide-top { - .molstar-layout-top { - display: none; - } - .molstar-layout-bottom { - width: 100%; - border-left: none; - } -} - -.molstar-layout-hide-bottom { - .molstar-layout-bottom { - display: none; - } - .molstar-layout-top { - width: 100%; - border-left: none; - } -} - -.molstar-layout-hide-top.molstar-layout-hide-bottom { - .molstar-layout-main { - top: 0; - } -} \ No newline at end of file diff --git a/src/mol-app/skin/logo.scss b/src/mol-app/skin/logo.scss deleted file mode 100644 index 7bd02b7d3a1a4595d15099b6f52aec9d1ea0f422..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/logo.scss +++ /dev/null @@ -1,47 +0,0 @@ -.molstar-logo { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - - display: table; - width: 100%; - height: 100%; - - > div { - display: table-cell; - vertical-align: middle; - text-align: center; - - > div { - display: inline-block; - position: relative; - width: 50%; - max-width: 390px; - height: 130px; - - > div { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - } - - > div:first-child { - //border-radius: 8px; - background: rgba(0,0,0,0.75) - } - } - } -} - -.molstar-logo-image { -@include non-selectable; - -background-repeat: no-repeat; -background-position: center; -background-size: 90%; -background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgoAAADKCAIAAABL1P+fAAAAAXNSR0IArs4c6QAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAALzZJREFUeNrt3flXG2eaL/D5B+65c3+ZM5Nk7ume7nOSnj7dyXSnE8eOMZlextN27HSWtoPpbJ3Ejh3HSzAk8QrYGINZDBiMWMVuMItYxSKJTQLEjgRIgMQqkMQuhCQgffu+hIzb/RYIkKpKVaXne56THxyo5ZWqPjwq1Vv/8FcIBAKBQAj5BxgCCAQCgQAPEAgEAgEeIBAIBAI8QCAQCAR4gEAgEAjwAIFAIBDgAQKBQCDAAwQCgUCABwgE8te/9oxP7o+I3xvB2xOe8FJ4wi/CEl4IS3z+buLP7iY+F5r8bGjyj0KSfxCS/K8hKc/cQZX6THDKM8GpT9/mP337u/8GpT19a6PSn7r5uDKfCkSV9VRg9lMBqHKerOh6JQw7BHiAQIAH4AECPEAgwAPwAAEeIBDgAXiAAA8QCPAAPECABwgEeAAeIMADBAI8YDx8lltO4vIRBsADBHiAQIAH4AECPEAgwAPwAGEOD221VfcvnyNW7HcVd/X8g426dj7++nne9QuoEm5cTPRfryT/i8kBF5MDL6QEfply82IqqlsX+UFfpn1X6bfXKyN4vbJCfFCVp4S552uga7k7KrkwVnthvO78BKr687qG85OoGs9PSc/rpecNsi8MTV8Ym76Ybv5ipuXsjPzsrPzsXOvZ+fb1Wmg/u9jxuanzc1PXmaWu0+au08s9py3flVX5ma33FKqV3lOr/SfXVCf/33QlvOmBBwiEBB6qctPPHXyJWOf/e70uHnr5S1SH9/i8/vKlIy/7Ht2D6qs3Xvn6D+v1zZt7r7y198rbe6++s+/aH/ddR3Vs343jr/offzXg3X2BXq+iuuW9Xrff248q+H2PsQGFu70AZoOiP+eX/Tm/UOf+x0DeC4N5LwzlP68peF5b8Pxw0c9HBD8bFfxsrPin4yX/PlH6E13ZTybLn5sSPqsXPmuo/PF09Y9QzdT826zoh3PiH8xLnlmofRqVqf5flhr+GdWy9J8ssv9jbfpHVCst/3tV/r/+okuFNz3wAIGwj4fsUB93ewFGxBeBB+ABeIAAD9vwcOcDj3F3aiBME0192S8CD8AD8AABHrbngX/jpPuM/oDgHeABeAAeIMDDjngI+cCjt6nGHYZ+XlvTm/Ui8AA8AA8QjvCQE31H09v9ffX1aJ+s/vUaxkrVM6JSPFmjqNR/q7CTv8d44Pl6ucPQqwVvYzwMFf3aYlRYpr8v68zj6rGhmv2+VjZqrnv1cc2v19rjWuj+9ruyDQYBD8AD8AChiQf0L+RuQWNxJsZD6If7e5s53kDMqIqUmb/EeJjpzSB3LStjfOABeAAeIGzlwWpZCv/s9xgPPD8vq8XM1UFfWzH35f4W40FT9ta3qyTvMvAAPAAPT+Z4uhgbHOqqddQAPJAQpawG4yH0o/1NpVlcfY/qezIVGS9iPCyOkN8wAQ/AA/AAPLCbB5RYn3cxHqI/P8zJBgK1Dr25v8V4GCp5i4p1AQ/AA/AAPLCeB9RAYDzc/cijuYyDDQRqHXoyfoXxsDBMybUW4AF4AB6AB9bzgBJ3yQvjIeYs1xoIm9nQnf4SxoO28mOKVgc8AA/AA/DABR7GBhQYD2F/9qhM49Q8faPSMCIPy0aqbhQHHoAH4AF44AIPKNmhPhgP4Z94LM4auPHWRK1DV9pLGA8j4ovUrRF4AB6AB/s8kHUSp27JwMPfGggiD5xpIEakYUQezAYK55gCHoAH4AF44AgPKDmhPhgPqIwTWrYPtEmv6OS/hPEwVn+D0pUCD8AD8MBSHkzWVeABj2FcS+ThUcQltr8vByp8iDysmKn9+wJ4AB44w0Nh9/BzIQUq/bw78IB2E+0s2mXgAU9FahjGQ+SnByaGWPwWR61DR8rLGA/jTXepXi/wADxwgwd0otzYFyeFYAUPGzZsLMS1QjCRh4VZA5GH/EgWNxDqCh8iD1S3DsAD8MANHh7b4LwQzOfhSRtcLgQTeVhvIPhhGA/3TrK1gZgfbW5PeRnjYbLtAQ2rBh6AB7bzgNngpBAM54Fog2uFYCgPqIGI/vwwxkPqFVZO9N2TdwzjoTf3t2srdNzuBzwAD6zmYVMbnBGCyTxsZYMLhWAoDyhNpVkYD1GnPPrlIna9v6cHRW3JezAe9D2Z9KwdeAAe2MuDHRscFoKxPNi3wVVCMJcHq8Ucc/YwxgPrGoiuh8cwHpQPf0dP6wA8AA/s5WFbGxwTgpk87MQGlwjBXB5QmsuyMB5QqdjTQOh7i+WJezAeaGsdgAfggaU87NAGB4RgIA87t4F+IRjNA2og7p87jPGQ4PO6jQ3z9KEWoT3tIMZDX8Ef6dwG4AF4YB0PdmzwK5E7KQTTeLBjw8m8xq3+F21CMJoHlL4WEcZDzOkDrcJs5r/LJzqykA0YD7MaWlsf4AF4YBcPdmzYOCdu9QM7FIJRPNixAUFo/wfoEYLpPKAkfuOF8cD8BgK1Dm38gxgPvfl/pHkzgAfggUU8bGuD/R/biRDM4WFbG7b9MRqEYAEPqIHAeGB+AzHentWS8ArGw+wQ3VdNgAfggS087NAGJ4VgCA87tMHlQrCAB5Tky14YD4mXXjfNMXRCROuSsZn3CsbDQIUP/VsCPAAPrOBhVzY4IwQTeNiVDa4Vgh08TAwqMR7unzkgzopg5nt9sDaCyINJr6B/S4AH4IH5PDhgg8NCuJwHB2xwoRDs4AElP/ISxkPs554MbCBQ69AUvw/jQe2K1gF4AB6Yz4PDNjgmhGt5cNgGVwnBGh4mhpREHhjYQPRXBhB5cEnrADwADwznwUkbHBDChTw4aYNLhGANDygF9y5hPMR97jmjG2bO231hUil7sA/jYVDk76rtAR6AB8byQIoNuxXCVTyQYgP9QrCJh8U5A5GH4hhf5rzjFcU+RB5sS0bgAQI8UGTDroRwCQ8k2kCzEGziAaUmIxzj4cFZz0kNI979qHWQPtiH8aCpd+WDsoEH4IGBPJBuw86FoJ8H0m2gUwiW8YAaCCIPJfcZ0UD0CC4ReXBh6wA8AA8M5IEiG3YoBM08UGQDbUKwjAcUUWYExkP8F65vIAxqcWPsXoyH0Waea7cKeAAeGMUDpTbsRAg6eUiTD1BnAz1CsI8Hm8Wc4PM6xkN24J9cu1XyDC+Mhzb+Qdom7gYegAfm80CDDdsKsSeqhDYe7EwsSOLOUioE+3hAaRVmYzzwzr820Oayib71KnFD7KsYDxMdWS4fKOABeGAID7TZsO3qXMsDuTZQLQQreUANROKl1zEesgNOuGp7WtK8MB5aU13fOnCGh/mFScOMZr2mNfr/qalp7UatrFqAB4bzQLMNuxKCTh6osIFSIVjJw0YDgfHAO+c52C6mf0tGW7PqY/ZjPIy3ZzFhlFjEw+LihF7fox6o6OzKbJBFiWqDHwnO5ArO5BSdzS48m1l4NqPwXHrBOX7B+dT8Cyn5F5IefZnwyAcVL+9SXK5vXK5fYoF/gSQxX5zUohR3DjRPGEdsq1bgweU8uMSGnQtBGw/U2UCdEGzlATUQ6Te8MR7Svjlqs9L6N/vqilmWcAjjoSPrXYaciZjMg8k0rptoVnTzpQ2B5aUflZV+XFLyiaDkU0HJqYLiU/mCz3bLw/2HX0U//OpezteoInIuh2WjunLv0c2cmlSpom7MMAo8uCQHecJNz1l7okpM1lUX4kQnD1TbsJGTeY2brh29BO7FA4q6VYTxkHjBs7OG1om+R+TZyAaMB+MAUx53yjQeVteWp3SyPkVKXfWp6vL3q8rfF5Z9KCz7iDoeQrKu3Mm8Gpx5NSjz+s2MG5nVfLlKrp/TAw/0/R1gXd1KCPTvLheCBh7osWGrR+k5M8gs5gEl44Y3xkP65SO0NRCrNnMj7xDGQ3umF3PGhyE8rK0tG3TSvs6oukovifCEuMJbVOHtEh5QBaT7+6f7RxZGC1urF8wLwIObC0E1D+y1gfU8oAYC4yHpIn0NxEBDQm30foyH2ZEW4OFxFudUQ70JzZIPG6uONVQdZw4PN9IDrvEDr6bdTKrM6NTQOmGie35zibFCUMoDq21gPQ8oj0I+w3hAtTRP+UTfFpNRErUf40FR7MOowXEhD9OTjf3tgc01b6GSVr/jDA+PSv1qGmKqG2JRVTbEVdbHCevjyuselNXFF9REOsnDZf7Nb/i3/LPCRN2N1hU6LmW77X0PzBSCOh7YbgMXeJjUKIk8NORSPtF3X3UEkYeFSWZNbuMSHmanGhTS0601b8hFb+6KB5ksorMrQz0gnNT3TM8MLVvmdrVenVGLqmugqUUpfiROSiwO2zkPX6Xe8k0NupYZJuqSUo2EO981zUAhKOKBAzZwgQeUkvu+GA/JX1LbQKDWQXzPA+OhR3CJaSNDMw9L8/1DHdc7xUfaRW/shIemRv/+vjzdRIvFMkvF9thWreOGEamiLrsmdSc8XEoJ8km5/U1GRNsQhedTN59ziWlCUMEDN2zgCA+ogSDy0JBHYQPRXRJI5IFprQOdPKytLY/3x/aIf98lPrQtDz0d9yd1MopIsJMxw2h1e1VUYZR9Hi4kB59PvnO3iK+bpeQvDJixlVFCkM4DZ2zgCA8opbF+GA8pPp56LSWXHOcmlKJID4wHtZiJD76mhwfTdGt/4zs9koP2eejrjJrSyVbXll0+LPo5fbGsJCg71A4P55JCziaGVHbKgAduC0EuD1yygTs8mOYMRB6E8ZRM9N2e50vkwWoyMnBYqObh27Xlyf6Yvtrf9Nb+biseWms/GNMIrJZpBo5Pl0ZxNz/GDg+o7hSkzZoWgQeuCkEiDxyzgTs8oNTmRGA8pKIGYpjkBgK1DjUR+zEeVKIIZo4JpTzYzMMj7V/01/5mKx7a694b1xStMaBdsJ9h/VhCZeZWPJxJCPXhR/eMDAEPnBSCLB5Eah3HbOAUD6iBIPJQySO5gWjL8yXywMzWgVIeLAu9Gtkb6rpfb8pDV92fdJoC5sPwZPrGBoPzYjfl4XTC3VO80FplJ/DAPSFYFJpt4BQPKHUPIzEe+L6eY/2k3aem6xNXh3tgPIy2ZjF2QCjiwaSXDNYfGKh/bVMetD1hNus0S49AUZd0Kx5O8sLTaquABxDCTWzgGg82qzn98hGMh4I7pD0pqD7BC+OhkXdolQETd9PJw5JeomnYvykPvfXHF6bb2H4cTs4ZwgSpm/LwSXw432khgAcQghU2cI0HlM6abIyHND9PTScJE33resVVYfsxHkbk2UweDdJ5WDJIhhte2ZQHTec1dn2aZD+CFsmmPHwcH5EqcUoI4AGEYIUNHORho4HAeCClgajnncB4aIg/zOTWgXQezAbJSOPeTXkwDj/i3mEpH+z1TbtH5OGjBxEPZfXAAwjBbRs4yMNGA4HxkO7nqWoqdmaZQ7LsyrseGA/jXcUMHwoSeVgxa8caX9mUh/mpOq4enLpZgw8/isjDBw8im9R9wAMIwWEbuMkDaiByg7wxHnL931hxdKLvVZu5JuowxoMs5QTz315k8bBmM+ia/4vIw6D0TdN0K7cPUd2s0YcfTeQBlVo3ATyAEFy1gZs8oAy2izEeMr56TSFx8DoBah2EoR4YD1P9YuaPA1k8GLpOjjf+CuNBI3vDujTqDgcqEuJiahSRh1NJcRabDXgAIThpA2d5QMkL8sZ4yA046kADgVqH6qjDGA/S5BOsGARSeFgc5k1IXyTysKivdZ82f2LGeCH1PsbDe3GRwcX5wAMIwUkbuMzDUIcY4yHza0caiO6KiIpQD4wHo6aFFYPgPA8riwqd7BdEHtzKhsdCEHnwjrtX3dMFPIAQ3LOByzygCON9MR6yvnnNPL+LO5yXF43lIR4YD+15vmwZAed5mG5/m8iDUR1F7WavWqZnhvrUwtbOLHFjjFAcaudpcSV1CYLahLZekWqkc3p+itINa1b3EXn4JIk3s5tJmejnAZ1xWkcNbCyRWvdcSIH7CLGVDWgQ0FBQNMhuyoNeqyDy0FQQuYvWoTyCyMPchNJNeDCPZeplL2A8THZ+RtHWLi5OKHvza+tvO/kw0dLGrM6B5kXzPBUbya+twnjwio1OFIuYzANXi2NCbGUD1eWmPKBU8nwxHtYbiIUdNRCodSgLPoDx0Mae1sFJHr61GYzy/8R4GGs+tGojeYKp1TXL4EC5WPQ16c+azhMn9w53kbu1lhWrX2YSxsO7sdH9Oh3wAEKwzga35kE/rCDy0FK4owaiKcuPyAOLWgcneTBpQg2yn2M8LOpKyTzVWmYV3fxtnzXtMA8bDxONLwpXaslEYkA3TuThZlEh8ABCsM4Gt+YBRZIRiPGQc8XTMLLNWX5mTFkW7InxoKwMZ9e+O8zDeuvQ9FOMh6nOUyRum2awVFx15slnTVPEw8azpmOLIsYMpH0NN1lSjfFw7P5OGwjgAYRgjg3uzsPSvIHIgzjFz/5vydZbB5wHy6LRTXgwa0KJPFgXeknZKpNpvEV6vbr8/ary92njYeNZ09XtVbYVq/O7MGNaPJ0ch/EQWFQEPIAQ7LLB3XlYP9fnR2A8oDJu3UCg1qHk9gGMB4UwgnU77hgPf/nWPNv8LMbDTL8/KZs0pZPVV58SVXjb56G4/Ms6aXSvWqibUhpnNCurls3tX56fnNb2DEqlXWVFksRteUDFK+ORIkRJWwvGwzv3Y0anZ1zOQ+uoIaZB+WSlyQeKeoafrOPpYu7VrapOdh2ehd0ueCGAh00aCCIPkq0biNqk00QeWNc6OMyDdSKDyMOajYSHak2M1EiEJ8QV3lvxUC26ouwtWFiccHgVWl1/dUtBbH7gVjwEpPsHPwzRz+mdvXCyYj2VFIfxEC8Su5wHCMROWMnDwqxB2VRTnhoW7+vF9z9J+vLbyhMxHnKveurUm9zdNqYQFwcdwHgYkpE/cbda8PZQxSdTHfGmiaYVs4GKUXWMh8WuoxgP00ofEi42qLLrKr224qG5KXx2dpCsHbetWvuGOxOLwzflwX9diFDnhciR1mM8fJCQsLzdNBvAAwR42GkM49pYn3dvv7c/+H2POx94hHzgEfrh/t7mGpJPlFZzbsBRjIeyCG/iT1bf98Z4qI46vGojeeLuOU2NMvOXvVkv9mW/2J/zy/6cX2jK3mICD2uLPfMtP8Z4sC06+8hug07aUHV8Ux6kDYEkwoClXd18Ly+IyMON9IDw/Girc58yzZgWMR7ejompV6mABwjwQE5G1QpkA8YDz8+L9HFRSLIxHvKueY50/90NTWM9YkHQAYwHKloHVdHbGA/q3P9gAg/L2hCMB337H51tDedUjVXHNuVhaLCU6uNh0TyfXZNK5OEaPzClytk3c5SwFOPhbnkF8AABHijkIfQj1ECIyF0RaiDyAo9iPJRF/m1yvRWbuSraG+Oh6h75rcO0SqDIeJGZPCy27cV4ME869ViLtbXlZsmHRB4kVWeoaxqIKW8WEHm4mnZT0t3gzGJl6n6MhzdjYux/vgQ8QIAHZ3mI/vyw1ULyeXmjgXiSh7zrnoPyku//om/ILrrpifEw3F5C7jasrZh7c3/LTB6+XdYstPwQ48HJi9JDvQnS6ncwHuqqT5lM4zQfGGVNxUQeLvNvzpsXnFnsJ0k8jIf6fjXwAAEeKOTh7kcezWVZpI+O4K43xoMg+AjqG1CVhR7BeBDHkT9xt74nsyfjV8zkwTaRjvEw0/2xUx/szKmaa94i8kC/DY+FIPKQJcl3Zpn3hOUYD3F2v78EPECABxJ4iDlLfgOh7RRjPDy68Vp/fc5G64DxMKEk+Zk/qHVQPvwdY3lYVp3FeDCPZTqzAX1tt4g8TOpkrjo2bKtWXhkP4+Eb/q2pOcc7JKlKhfFwip8OPECAB2p5CPuzR3M5+Q1ESZg3xkPxnSOlIUcwHsRx3qSveqo7qzv9JcbyYJL/X4yHVbPW4bWbl8aQDRgPis4Y1x4ehjk9kYd8qeNXyGdMixgPf4i+P71oAh4gwAO1PNw/d3hxluR7Aoa7xBgP+f6ehQGeGA8zYyTPvmczG7rSXmIsD2umHiIPTjVqffFEHiyWWZcfIcWyEoyHr1JvOfMl13PpfIyHOpUaeIAAD9TyEP6JR2VaGOljJE7xs8+DLMuP9JWOSMOYzMOqvgDjYa73gjNrb697D+NBpUhiwhGyYF4g8tAx5PhfA4liEcZDnrwVeIAAD5TzgIr0BsIworTPA/mtw5Kxk/8Sk3mwaoMxHpy58DBn7JCL3sR4sDKgddjIw7pHGA/pkgKHl1bV04XxcL1IADxAgAc6eKhKJ38mbUmK31Y8SDPJbx00In+G87CsOoPxYJt1/JHa2l4exkNfZxRzDhL1+ADGg29qkMNLU+kmMB5OJCQCDxDggQ4eIj89MK3Tkrte44hyKx4WDCSvy6RXdKS8zHAeluRPYzw4c126W3oa40GvkzLqOCHyoNWPObw0jIejMfeBBwjwQD4PPF8vIg/5kZdIHylpTiCRh44y8ifuVlf4sJEHh9e7trbcWvMGxoPVMs2o4yS1MgPjQdrX5vDS/pzIw3jonZgEHiDAA8k8PLzrU8EPw3i4d/LAxBDJ1wPMC0YiD8tkT9xtmlK0p7yM8TAuu8soHr419WA8TMs9Hd/leRXGQ2v9OaYdJ7XdDRgPeY1lDi/tZlEh8AABHujgYWHWQOSh4B75DYRcEPkkD+2l5LcOqnIfIg8rZgPDeZjvPe/wemcmGzEeFK1BTDtOVOMDGA/xQsdvsiHyULfF1BrAAwR4cIoH9O9CfhjGQ9QpDyoaiMc8lIUeWV4guXWYHhS1Je/BeNC18dD/YhQPa/MyEnmY1BZgPIxqBEw7Tkb0oxgPkcXJDi+tsLUV4yFP3gY8QIAHSniwWswxZw9jPKReIX+i766qxA0eVA3kT9zd9fAYxoPy4e/WVsxM42FFx8d4WBp+wG0erCtWjIdLKY63OMADBHigjweU5rIsjAdUKjnZE33bzBuTaqyQPnH3oEieuAfjQd/z/c0EDOdheTzD4fUOdYdjPOhGaxh4qAAPEOCBrTygBuL+ucMYD2nXyJ9FdWNKPipaB4wHRc73rQO3eVC3B2A8LMypgAfgAQI8kMbDegNRnoXxEHP6QHddMbnbsDGhN7nLnOjIQjZgPBj7//YZC/DAJR7atcMYD9cKBcADBHigkAfUQCR+44XxkODzuo3sib7JDWoR2vgHMR568//uqZzAA5d46NfpgAcI8EArDyh9LSKMB1Stwmwmvwbj7VktCa9gPMwOiYAH4IEJPLSOGjhZ7DpTq/Tz9A8R13hASb7shfGQeOl1m5WhDQRqHVpTD2I8KPOOYT8GPAAPVPAQXa8kngLcofxK5OziobB7mAnjxnoe+ltEGA/3zxxoq8xi5qs+WBvRzHsF42F+rBl4AB6AB7CBaUKwngeU/MhLGA+xn3ua5hjXTlqXjE3x+zAe1BWb7BHwADwAD+5sA0OE4AIPE0NKIg/irAimvdiDkggiDya9AngAHoAHsIGBQnCBB5SCe5cwHuIY1kCg1kH2YB/Gg6p8890BHoAH4AFscLkQHOFho4HAeJBkM6iBUBT7EHkwTSmAB+DBhTzsiS49ni5mae2JKuG8DdsKgQaBuhHmCA8oZbwAjIcHZz0nNUomvLoLk0rpg30YD5r6LR+UDTwAD/TwgP6FpWdMlX7+uZACd7DBvhBoENBQ0L89LONhcc5A5KHkvi8TXtoewSUiD7YlI/AAPAAPYAMbhWAZDyiizAiMh/gvXN9AoNahMXYvxoOd1gF4AB6AB7CB4UKwj4eNBgLjoTTWz7WvaEfuSYyHNv5BO60D8AA8AA9gA8OFYB8PKI2FPIwH3vnXBtpErnot9SpxQ+yrGA8THdvctQc8AA/AA9jAZCFYyYPNYk689DrGQ3bACVe9kC1pXhgPrakHH0/cDTwAD8AD2MBGIVjJA0qrMBvjgXfOc7Bd7JLWoT5mP8bDePv2E34AD8AD8AA2MFkItvKw3kD4HsF4yLnpTfOLt7piliUcwniQp/x+29YBeAAegAewgeFCsJUHlLbKLIyHxAuenTW0TvQ9Is9GNmA8GAd2dBUEeAAegAewgclCsJgHlIwb3hgP6ZeP0DbR96rN3Mg7hPHQnum1w18HHoAH4AFsYLIQ7OZB3SrCeEi6SF8DMSzPro3ej/FgVO/0+gfwADwADy63wWRdBSG4yQNKpr83xgM9DYTFZGyIP4zx0Lbj1gF4AB6AB5fbgNZC1jPm0CDTIA3NQrCehxFlM8YDqpaSBKpfp77qCEnUfoyHhcldHIfAA/DgzjwwwQa0LrJ4OJ4uPsgTckwI1vOAUnLfF+Mh+UvPpXkKJ/pGrYP4ngfGQ4/g0q4WAjwAD27LA0NsIJcHtDSOCcEFHiY1SiIPDXkUTvTdWx1B5GFXrQPwADy4LQ/MsYF0HjgmBBd4QCmN9cN4SPGhqoEwTWtFkR4YD7ttHYAH4ME9eWCUDVTwwCUhOMLDegNB4EEYT8lE3+15vkQerCYj8AA8AA/ssoEiHjgjBEd4QKnNicB4SPXx1A8ryN3auQllTcR+jAeVyJEPsoAH4MGteGCgDdTxwA0huMODac5A5KGSR3ID0ZbnS+TBgdYBeAAe3IoHZtpAKQ8cEII7PKDUPYzEeOD7ktlAGDTN1eEeGA+OtQ7AA/DgPjww1gaqeWC7EJziATUQRB5Koz4ja1PrE7wwHhp5h1ZXHLwFD3gAHtyBBybbQAMPrBaCUzygdNZkYzyk+XlqOkmY6FvXK64K24/xMCJ3fAIP4AF4cAcetjpv7okqcbkN9PBAmxCkDzXXeLBZzemXj2A8FNz5EwmtA+8ExkND/GGHWwfgAXhwEx7QaRGdHF3SPWxrA2080CDEVjsL3QPeQGA8pPt5ap1rIEY6SirvemA8DMudmvsPeAAe3OTag0uE2IkNdPJAqRBU2MBNHlADkXHlCMZDYYj3iqPz9K3azDVRhzEeZCkn0L8DD8AD8MBAIXZoA808UCQERTZwkweUwXYxxkPGV68pJA7+sT8kyxaGemA8TPU7ez0DeOASD+3aYeCBIUJsdbpEayduAHU8bHVBnlwhqLOBszyg5AV5YzzkBhx1oIFALUJ11GGMB2nyCee3EHjgEg+Fra0YD6kNUuCBfiHs2IDWTjyJU8eDSK3bamfJEoJSG7jMw1CHGOMh82tHGohBWXZFqAfGw2Q/CV+F4jAPQ93hGA8GndTdeMiTtwEPNAth34ZNT+LU8YCWbGdnnReCahu4zAPKoyBvjIe8wKPm+V3c4by8aCwP8cB4aM8j505shvOwNPzA4fVOagswHkY1AqbZYF2xAg9cEmJbG+jnwf7OOiMEDTZwnAe9VoHxkPXNa00FkTtfQnd5BJGHuQlyDjZG8bA2L8N4mO89z20eRvSjGA+RxcnAA0uF2IkNLuGBCiHosYHjPKBU8nwxHlCZF3bUQKDWoSz4AMZDWx5pkzgxiodvTT0k8mAYq8R4ULQGMe0MpRofwHiIF2Y5vLSIinKMh/LuHuCBHiF2aIOreCBXCNps4D4P+mEFkYeWwh01EN3lkUQeyGodmM/DTMdbjh/58yqMh9b6c0w7PdV2N2A85DWWOby0m0WFGA+9E5PAAw1C7NwGF/JAlhB02sB9HtYbiARfjIecK57z+mH7vzUzpiwL9sR46BQEkrhhjOIBBePB2PRTh9e7traM8dBYdcxqmWbUuSm1MgPjQdTl+PXzL9L5wAP9QuzKBtfy4LwQNNvgFjzMTQ0TeRCn+Nn/LVmWH5EHy6KRxA1jPg+rZq3Dq+6WnsZ40DPsy0vX+IEYD1r9mMNLO3Y/GuNh2WYDHigVYrc2uJwHZ4Sg3wa34GH9XJ8fgfGAyjiitNM6lNw+gPGgEJL88Gqm8bCsOoPxYJttcXjV2l4exkNfZxRzTknq8QEiDw4vbWx6hsjDVj8MPJAihAM2MIEHx4RwiQ3uwsPSvIHIg2TrBkKa6UfkgdzWgYE8WLXBGA/msUyHVz092Yjx0FB1fHVtmSHno2JZCcZDuqTA4aV1DA9jPFwvEgAP1AnhmA0M4WG3QrjKBnfh4bsGIhLjIffq5g3EmEJcHHQA46FfkkD6JjGNh5UJPsbDXO8Fh1e9trZM5GFkqJgJZ6IF88KN9ACMB2l/m8MLzJQ2YjzEisTAA0VCOGwDc3jYuRAutMGNeFixmnMDjmI8lEV4E3+y+r43xkN11GEnZ99jBQ9rph6MB6P8P51Zu7YvHuNBWvMJExoI1DoQebCuWB1e4C1BIcbDVt9qBR6cFMIZGxjFw06EcK0NbsQDikKSjfGQd81zpFv0d61Dj1gQdADjYUiWTcX2MI2H9ffr3/NgkP3cmavTi/MqjIe6Sq9+RYprT0CGOb1/uj/GQ7601JllvhsbjfHQp5sEHkgXYk9UiZNfDGUUD/Z3dqsZ/Wizwb14QA1EXuBRjIeyyL+bXK8q2hvjoeoeJa0DM3kwK/+E8bA86dTHQX1ttzAeJMITRkOXq049tlUrr4xH5GHYie8sqXQTRB7s/Dzw4MxJ08nbypjGw253lk4b3IuHxw3EkzzkXfcclH//pD1VQ3bRTU+Mh0FqWgdm8mAbi8V4mOn+2JkNWJxTEXmorz5lMo275LxT1lQckO6P8ZBUmenMMrOkjRgPNwoFwAM9Quz2lmMG8rDznaXZBrfjATUQgrveGA+C4CMrNjOqstAjGA/iuBPUDT0DeVgz9WA86GUvrNmcOn7U3ZEYD+IKb2mtz+qahX4bbmbcIPIwb15wZrHn0/kYDxVbX3gAHkgUwoEJi5jJw052ln4b3I4HFG2nGOPh0Y3X+utzNloHjIcJpZi6LWEgD+t/77ftxXgwO/f5ktU63Sz5EONBVOEtqTpDZw9R3ixANhB5kHQ3OLPYsRmjV2w0xsPI9AzwQLUQjk1mx1ge/rrddQj6bXBHHlBKwrwxHorvHCkNOYLxII7zpnQzmMnDsjYE48HQ/YmTmzFj7CTyUF3+vrjqjG6imeq3uG3Vml2TGpR5nchDbGmikwvPltZjPHyWlmb/V4AH50+aDk+FzWQettpZV9ngpjwMd4kxHvL9PQsDPDEe9INySjeDmTyszjVhPOhkv7AtKpxt2lTZRB6qyt8Xln3Y2R5nscxSNMjt6uZ7eUHBmVeJPARlhzrzZdaNfJr0AOMhrbEReKBUCGcek8BwHog760Ib3JQHFGHsafs8yLL8qN4GZvKw/vlS11GMh7mBcOc3Rq1M2pQHYdlH5aUfdXenkYtE33BnYnF4SNaVO5lXiTwEPwzVz+mdXIVM3ecddw/jYXrRBDxQJ4STD1ljPg9P7qxrbXBfHgwjSvs8zIxRfkQxlgfrRAbGw4T0RScvUG9EpUjaioey0o9LSj6RyiLHxuUrq45ftdbq+qtbCmLzA8OyL4dlX9mUh+CHIc7bgOKTkYzx4Pfw4ba/BTw4fNL0K5E7+QBOVvCwsbMn8xpda4P78oAiSfHbigdpph8NG8BYHr61GYg8kNJArH+yN1RihwdByaeCklMFxadEtcHdyqJBbb1xRmNfi8lp7bCur61XVCRJjH741b2cr1FF5FzeigdeGW/Bua8qbaRJ3fdeXCTGQ4NKBTwwOWzhgSFxXx6MI8qteKChdWAyDyhmTSjGw3jjr9Zs5ExKODc7UFd9yj4P+YLPHgnO5ArO5BSdzS48m1l4NqPwXKEwoLIhrrI+Lq/iVtKjLxMe+aDi5V2Ky/WNy/W7//CrbXmobq+yOX29YSOXMpMxHj5M3NHEXMAD8AA8MJ0HFGlOIJGHjrIIetbOZB5QA0Hkwagg7UGqq2vLvT2pu+UhveAcv+B8av6FlPwLu+UhtihizDBK1vaj1uGDB5EYDwWtrcAD63hIkw+g87jzRfzGEfDAbh7MC0YiD8tkT9zNRh7WP/3UhGI8jDW+sjxL5re5TKZxeXMY1TzEF4W3qcn8+qxlxXo6OQ7j4c+JvK2e/wM8MJkH6gp4YDcPKHJB5JM8tJdG0LZqhvOAGggiD2PNh75dI3kGKotltqebX1X5Bek8ZAhje4fJn98prrIE2YDxULiz1gF4AB6AB9bwgBqIJ3lYXjDStmqG84CyNByP8TDSuHeqx5eK0Vhdtej1PZ1dGeXCi07ykC9O6hxoXjRT8q2P7hHNRw8iMB7OpfN3vgTgAXgAHtjBA0pXVeIGD6qGbDrXy3we/rJmNsh/jfEw3PDK3OhDSkdmYXFidEzepxbWSqMrJaH2ecgqvy2oTZC0PuoZaNIZtZRu2Kxp8VxKLJGHjuFh4AF4AB44yMOKzbwxqcYKNRN3s5cHFOtsC5EHTcP+pZlW+t+scwuT+mnNRtG/dsuK9WZ+xsfxERgP94S7O7kDD8AD8MAaHlA2puSjeaWs4AFlfiicyINWdsRmHnarM0t8VfEn8eEYD58mPdjhFWnggQm5VdWJhKCnXH5TG/BAWgNBc+vAIh7+smaeajuO8TBYf0Aje8O6NOomp5X0OuFJXjiRh87hXfcxwAMEeGATDy4JW3hYX45Zq2v+L4yHgfrXBqVvuoMQmXWVp3ihRB5ypPUOLA14gAAPwAN3eEAxG8REHtR1v1Y3vsVtITLrhKcT7hJ5CCnOd2yBwAMEeAAeOMXDd0JIiDz01/6mr/Y381N13HuBLCvWkIK0MwmhRB6uP8q0ODo5B/AAAR6AB67xgDIzELkpD721vxvvj11bW+bMq6OZGvdNu3c2MYTIg19mksWJiZuABwjwADxwkAeUaXXkpjz0SA4OtH5p4cQHTdVdsnNJIcgGIg/nUmLHZ5y6dxJ4gAAPwAM3eUCZG324KQ894t93iQ9NaQvY20Zo9WPhgpTzyXc25eFmfobF6QlfgQcI8AA8cJYHlEV97VY8dIqPKKSnpycb2fVyzJsX8hrLfFJuX0gO3pSHW2TYADxAgAfggeM8oNjMw4PSNzfloV30RmvNG13SM0Y2IGFdsYq7G65nhV1KCdqKh/Q6IVmrAx4gwAPwwHEeUL5dWx7turoVD3LRm801b3U2fm6YlK4y8uMm/ZyhUFr6Df/WV6m3fFODNuXBhx/VMtBL4kqBBwjwADxwn4eNGIfz7PCASlr9TrP4z2pl0pJpnAkjb1uxdmsUcSUJV9NuXubftMNDSEGabpbkSXyBBwjwADy4Cw8olqVRTec1Ozw0Vh1rqDpeV+nVVHdxoD93bnaA/gFfMM/3aLvz6nL90/1vpAdc4wfa4eHr9HuVnTIqNgN4gHCWh406/9/rdfHQy1+iOrzH5/WXLx152ffoHlRfvfHK139Yr2/e3Hvlrb1X3t579Z191/647zqqY/tuHH/V//irAe/uC/R6FdUt7/UCHjZ4GMh7YTDvhaH85zUFz2sLnh8u+vmI4Gejgp+NFf90vOTfJ0p/oiv7yWT5c1PCZ/XCZw2VP56u/hGqmZp/mxX9cE78g3nJMwu1T6My1f/LUsM/o1qW/hM9PGxkbqq+T3bSPg8S4QlxhbeowltSdaarPXZosHR2dpC6TVo0zyu1XaL2ytiiiJsZN1AFpPtvy0OKqHBuaYGiTSLy8EJY4vN3E392N/G50ORnQ5N/FJL8g5Dkfw1JeeYOqtRnglOeCU59+jb/6dvf/Tco7elbG5X+1M3HlflUIKqspwKznwrIBh4gwAPwwCweUNbWlqe0BV11f9qWh+ry95981nRD/c3W1nj1QMXYuHx6ZmjZMrfrVmnVojNqJ4wjLUpxXWdFnjjpyWdNB2Ve3wkP8cJsjX6M0iECHiDAA/Dgjjw8RkKnKeiSntk5D1s9a7pSEipuiKlpiKluiEVV2RBXWR8nrI8rr3tQVhdfWhdfUpdg/1nTO+SBV5mlpRgG4AECPAAP7s7D4xgnG/vabjnDgzPPmt4JDzez71a01sybF2gbE+ABAjwAD8DD97Fap0c1Ann9BUbxkCN51KVR0D8awAMEeAAegAc8S6bx8RFRR0uIq3iIKYoskZWoxwesZNz/DDxA3JoHCISizM0ODg2WypvDaqo+p5SH1PIH5c1FCm3Xgnkehh0CAR4gbIrFMjs7OzgwUKHszZfKohpkUY7xwC8NyRcnVbcUNCtrNRP9xnk9jC0EAjxAOJiVVYtxRoPKsFHTGv3/1NS0dqMmp7WmZWgLIBDgAQKBQCDAAwQCgUCABwgEAoEADxAIBAIBHiAQCAQCPEAgEAgEeIBAIBAIR/P/AbAvdi1UGXhFAAAAAElFTkSuQmCC'); -} \ No newline at end of file diff --git a/src/mol-app/skin/molstar-blue.scss b/src/mol-app/skin/molstar-blue.scss deleted file mode 100644 index 0d870a8c673de9f831209b771d645b4cc511440b..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/molstar-blue.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'colors/blue'; -@import 'base'; \ No newline at end of file diff --git a/src/mol-app/skin/molstar-dark.scss b/src/mol-app/skin/molstar-dark.scss deleted file mode 100644 index cdf80ffd913790db09cc67a424f3392c9ec1c01b..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/molstar-dark.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'colors/dark'; -@import 'base'; \ No newline at end of file diff --git a/src/mol-app/skin/molstar-light.scss b/src/mol-app/skin/molstar-light.scss deleted file mode 100644 index d45b6bc81bedb18f0c0a6a2efd734bcd3d454670..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/molstar-light.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'colors/light'; -@import 'base'; \ No newline at end of file diff --git a/src/mol-app/skin/ui.scss b/src/mol-app/skin/ui.scss deleted file mode 100644 index cd572232a6843ab134fca6b60e97568d8a4730ee..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/ui.scss +++ /dev/null @@ -1,39 +0,0 @@ -@mixin non-selectable { - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+ */ - /* Rules below not implemented in browsers yet */ - -o-user-select: none; - user-select: none; - - cursor: default; -} - -::-webkit-scrollbar { - width: 10px; - height:10px; -} - -::-webkit-scrollbar-track { - //-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.8); - border-radius: 0; - background-color: color-lower-contrast($control-background, 4%); -} - -::-webkit-scrollbar-thumb { - border-radius: 0; - //-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.9); - background-color: color-lower-contrast($control-background, 8%); -} - -@import 'components/controls-base'; -@import 'components/controls'; -@import 'components/entity'; -@import 'components/help'; -@import 'components/jobs'; -@import 'components/log'; -@import 'components/misc'; -@import 'components/panel'; -@import 'components/slider'; -@import 'components/viewport'; -@import 'components/sequence-view'; \ No newline at end of file diff --git a/src/mol-app/skin/variables.scss b/src/mol-app/skin/variables.scss deleted file mode 100644 index ddbf57aab8c4950b03ff37bcabdcc1295060613c..0000000000000000000000000000000000000000 --- a/src/mol-app/skin/variables.scss +++ /dev/null @@ -1,78 +0,0 @@ - -// measures - -$control-label-width: 110px; -$row-height: 32px; -$control-spacing: 10px; -$entity-subtree-offset: 8px; -$info-vertical-padding: 6px; -$slider-border-radius-base: 6px; - -// layout -$expanded-top-height: 100px; -$expanded-bottom-height: 3 * $row-height + 2; -$expanded-right-width: 290px; -$expanded-left-width: 290px; - -$expanded-portrait-bottom-height: 10 * ($row-height + 1) + 3 * $control-spacing + 1; -$expanded-portrait-top-height: 2 * $row-height + 1; - -$standard-bottom-height: 8 * ($row-height + 1) + 3 * $control-spacing + 1; -$standard-top-height: 2 * $row-height + 1; - -////////////////////////////////////////////////// -// ENTITY COLORS - - -// entity colors are "somewhat orthogonal" on the RGB cube -// TypeClass = 'Root' | 'Group' | 'Data' | 'Object' | 'Visual' | 'Selection' | 'Action' | 'Behaviour' - -// DO NOT CHANGE THESE!! -$entity-color-Root: $default-background; -$entity-color-Data: color-lower-contrast(#95a5a6, 15%); -$entity-color-Selection: color-lower-contrast(#e74c3c, 15%); -$entity-color-Action: color-lower-contrast(#34495e, 10%); -$entity-color-Object: color-lower-contrast(#2ecc71, 10%); -$entity-color-Behaviour: color-lower-contrast(#9b59b6, 10%); -$entity-color-Visual: color-lower-contrast(#3498db, 5%); -$entity-color-Group: color-lower-contrast(#e67e22, 5%); - -////////////////////////////////////////////////// -// COLORS and COMPUTED COLORS - -$slider-disabledColor: #ccc; - -$control-background: color-increase-contrast($default-background, 6.5%); -$border-color: color-increase-contrast($default-background, 15%); -$molstar-form-control-background: color-lower-contrast($default-background, 2.5%); - -// buttons -$molstar-btn-link-font-color: $font-color; -$molstar-btn-link-toggle-on-font-color: $font-color; -$molstar-btn-link-toggle-off-font-color: color-lower-contrast($font-color, 33%); - -// used for "actions" -- i.e. + in selection -$molstar-btn-remove-font-color: $font-color; - -$molstar-btn-action-background: $molstar-form-control-background; - -// update selection etc -//!! $molstar-btn-commit-on-font-color: $entity-current-font-color; -$molstar-btn-commit-on-hover-font-color: color-lower-contrast($molstar-btn-commit-on-font-color, 20%); //!!Change -$molstar-btn-commit-on-background: color-lower-contrast($default-background, 2%); -$molstar-btn-commit-off-background: color-lower-contrast($default-background, 4%); //$control-background; -$molstar-btn-commit-off-font-color: $font-color; - -// log -$log-font-color: color-lower-contrast($font-color, 5%); -$log-timestamp-font-color: color-lower-contrast($font-color, 20%); - -// highlight -$highlight-info-font-color: $hover-font-color; -$highlight-info-additional-font-color: color-lower-contrast($hover-font-color, 20%); - -// entity state -$entity-color-fully-visible: $font-color; -$entity-color-not-visible: color-lower-contrast($font-color, 66%); -$entity-color-partialy-visible: color-lower-contrast($font-color, 33%); -$entity-tag-color: color-lower-contrast($font-color, 20%); \ No newline at end of file diff --git a/src/mol-app/ui/controls/common.tsx b/src/mol-app/ui/controls/common.tsx deleted file mode 100644 index 90125044172357c28a8def3b58c8290deecf9024..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/controls/common.tsx +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import * as React from 'react' -import { shallowEqual } from 'mol-util' - -export type ButtonSize = 'xs' | 'sm' | 'normal' | 'lg' - -export type ButtonStyle = 'link' | 'remove' | 'default' - -export abstract class Pure<Props> extends React.Component<Props, {}> { - shouldComponentUpdate(nextProps: any, nextState: any) { - return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState); - } -} - -export class Button extends Pure<{ - onClick: (e: React.MouseEvent<HTMLButtonElement> | React.TouchEvent<HTMLButtonElement>) => void, - size?: ButtonSize, - style?: ButtonStyle, - active?: boolean, - activeStyle?: ButtonStyle, - icon?: string, - activeIcon?: string, - disabled?: boolean, - disabledStyle?: ButtonStyle, - asBlock?: boolean, - title?: string, - customClass?: string, - customStyle?: any -}> { - render() { - - let props = this.props; - - let className = 'molstar-btn'; - if (props.size && props.size !== 'normal') className += ' molstar-btn-' + props.size; - if (props.asBlock) className += ' molstar-btn-block'; - - if (props.disabled) className += ' molstar-btn-' + (props.disabledStyle || props.style || 'default'); - else if (props.active) className += ' molstar-btn-' + (props.activeStyle || props.style || 'default'); - else className += ' molstar-btn-' + (props.style || 'default'); - - if (props.customClass) className += ' ' + props.customClass; - - let icon: any = void 0; - - if (props.icon) { - if (props.active && props.activeIcon) icon = <span className={ `molstar-icon molstar-icon-${props.activeIcon}` }></span> - else icon = <span className={ `molstar-icon molstar-icon-${props.icon}` }></span> - } - //onTouchEnd={(e) => { (e.target as HTMLElement).blur() } } - - return <button - title={props.title} - className={className} - style={props.customStyle} - disabled={props.disabled} - onClick={(e) => { props.onClick.call(null, e); (e.target as HTMLElement).blur() } } - > - {icon}{props.children} - </button> - } -} - -export const TextBox = (props: { - onChange: (v: string) => void, - value?: string, - defaultValue?: string, - onKeyPress?: (e: React.KeyboardEvent<HTMLInputElement>) => void, - onBlur?: (e: React.FormEvent<HTMLInputElement>) => void, - placeholder?: string -}) => <input type='text' className='molstar-form-control' placeholder={props.placeholder} value={props.value} defaultValue={props.defaultValue} - onBlur={e => { if (props.onBlur) props.onBlur.call(null, e) } } - onChange={e => props.onChange.call(null, (e.target as HTMLInputElement).value)} onKeyPress={props.onKeyPress} />; - -export function isEnter(e: React.KeyboardEvent<HTMLInputElement>) { - if ((e.keyCode === 13 || e.charCode === 13)) { - return true; - } - return false; -} - -export function TextBoxGroup(props: { - value: string, - onChange: (v: string) => void, - placeholder?: string, - label: string, - onEnter?: (e: React.KeyboardEvent<HTMLInputElement>) => void - title?: string -}) { - return <div className='molstar-control-row molstar-options-group' title={props.title}> - <span>{props.label}</span> - <div> - <TextBox placeholder={props.placeholder} onChange={props.onChange} value={props.value} onKeyPress={(e) => { - if (isEnter(e) && props.onEnter) props.onEnter.call(null, e) - } } /> - </div> - </div>; -} - -export const CommitButton = (props: { - action: () => void, - isOn: boolean, - on: string, - off?: string, - title?: string -}) => <div style={{ marginTop: '1px' }}><button onClick={e => { props.action(); (e.target as HTMLElement).blur(); }} - className={'molstar-btn molstar-btn-block molstar-btn-commit molstar-btn-commit-' + (props.isOn ? 'on' : 'off')} - disabled={!props.isOn} title={props.title}> - <span className={ `molstar-icon molstar-icon-${props.isOn ? 'ok' : 'cross'}` }></span> - {props.isOn ? <b>{props.on}</b> : (props.off ? props.off : props.on) } - </button></div> ; - -export const Toggle = (props: { - onChange: (v: boolean) => void, - value: boolean, - label: string, - title?: string -}) => <div className='molstar-control-row molstar-toggle-button' title={props.title}> - <span>{props.label}</span> - <div> - <button onClick={e => { props.onChange.call(null, !props.value); (e.target as HTMLElement).blur(); }}> - <span className={ `molstar-icon molstar-icon-${props.value ? 'ok' : 'off'}` }></span> {props.value ? 'On' : 'Off'} - </button> - </div> - </div> - -export const ControlGroupExpander = (props: { onChange: (e: boolean) => void, isExpanded: boolean }) => - <Button style='link' title={`${props.isExpanded ? 'Less' : 'More'} options`} onClick={() => props.onChange.call(null, !props.isExpanded) } - icon={props.isExpanded ? 'minus' : 'plus'} customClass='molstar-conrol-group-expander' /> - - -export const RowText = (props: { - value: any, - label: string, - title?: string -}) => <div className='molstar-control-row molstar-row-text' title={props.title}> - <span>{props.label}</span> - <div> - {props.value} - </div> - </div> - -export const HelpBox = (props: { - title: string, - content: JSX.Element | string -}) => <div className='molstar-help-row'> - <span>{props.title}</span> - <div>{props.content}</div> - </div> - -export function FileInput (props: { - accept: string - onChange: (v: FileList | null) => void, -}) { - return <input - accept={props.accept || '*.*'} - type='file' - className='molstar-form-control' - onChange={e => props.onChange.call(null, e.target.files)} - /> -} \ No newline at end of file diff --git a/src/mol-app/ui/controls/slider.tsx b/src/mol-app/ui/controls/slider.tsx deleted file mode 100644 index 23a2387bb66d2c7af3a0d57509c737bb12f273e3..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/controls/slider.tsx +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import * as React from 'react' -import { TextBox, isEnter } from './common' - -export class Slider extends React.Component<{ - label: any, - min: number, - max: number, - value: number, - step?: number, - title?: string, - callOnChangeWhileSliding?: boolean, - onChange: (v: number) => void -}, { value: string }> { - - state = { value: '0' } - - private firedValue = NaN; - - componentWillMount() { - this.setState({ value: '' + this.props.value }); - } - - componentWillReceiveProps(nextProps: any) { - this.setState({ value: '' + nextProps.value }); - } - - private updateValue(s: string) { - let v = +s; - if (v < this.props.min) { v = this.props.min; s = '' + v; } - else if (v > this.props.max) { v = this.props.max; s = '' + v; } - this.setState({ value: s }) - } - - private fire() { - let v = +this.state.value; - if (isNaN(v)) { v = this.props.value; } - if (v !== this.props.value) { - if (this.firedValue !== v) { - this.firedValue = v; - this.props.onChange.call(null, v); - } - } - } - - render() { - let step = this.props.step; - if (step === void 0) step = 1; - return <div className='molstar-control-row molstar-slider' title={this.props.title}> - <span>{this.props.label}</span> - <div> - <div> - <div> - <SliderBase min={this.props.min} max={this.props.max} step={step} value={+this.state.value} - onChange={v => { - this.setState({ value: '' + v }); - if (this.props.callOnChangeWhileSliding) this.fire(); - }} - onAfterChange={v => this.fire()} /> - </div> - </div> - <div> - <TextBox value={this.state.value} onChange={v => this.updateValue(v)} onBlur={() => this.fire()} onKeyPress={e => { - if (isEnter(e)) this.fire(); - } } /> - </div> - </div> - </div>; - } -} - -/** - * The following code was adapted from react-components/slider library. - * - * The MIT License (MIT) - * Copyright (c) 2015-present Alipay.com, https://www.alipay.com/ - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -function classNames(_classes: { [name: string]: boolean | number }) { - let classes = []; - let hasOwn = {}.hasOwnProperty; - - for (let i = 0; i < arguments.length; i++) { - let arg = arguments[i]; - if (!arg) continue; - - let argType = typeof arg; - - if (argType === 'string' || argType === 'number') { - classes.push(arg); - } else if (Array.isArray(arg)) { - classes.push(classNames.apply(null, arg)); - } else if (argType === 'object') { - for (let key in arg) { - if (hasOwn.call(arg, key) && arg[key]) { - classes.push(key); - } - } - } - } - - return classes.join(' '); -} - -function noop() { -} - -function isNotTouchEvent(e: TouchEvent) { - return e.touches.length > 1 || (e.type.toLowerCase() === 'touchend' && e.touches.length > 0); -} - -function getTouchPosition(vertical: boolean, e: TouchEvent) { - return vertical ? e.touches[0].clientY : e.touches[0].pageX; -} - -function getMousePosition(vertical: boolean, e: MouseEvent) { - return vertical ? e.clientY : e.pageX; -} - -function getHandleCenterPosition(vertical: boolean, handle: HTMLElement) { - const coords = handle.getBoundingClientRect(); - return vertical ? - coords.top + (coords.height * 0.5) : - coords.left + (coords.width * 0.5); -} - -function pauseEvent(e: Event) { - e.stopPropagation(); - e.preventDefault(); -} - -export class Handle extends React.Component<Partial<HandleProps>, {}> { - render() { - const { - className, - tipFormatter, - vertical, - offset, - value, - index, - } = this.props as HandleProps; - - const style = vertical ? { bottom: `${offset}%` } : { left: `${offset}%` }; - return ( - <div className={className} style={style} title={tipFormatter(value, index)} - /> - ); - } -} - -export interface SliderBaseProps { - min: number, - max: number, - step?: number, - defaultValue?: number | number[], - value?: number | number[], - marks?: any, - included?: boolean, - className?: string, - prefixCls?: string, - disabled?: boolean, - children?: any, - onBeforeChange?: (value: number | number[]) => void, - onChange?: (value: number | number[]) => void, - onAfterChange?: (value: number | number[]) => void, - handle?: JSX.Element, - tipFormatter?: (value: number, index: number) => any, - dots?: boolean, - range?: boolean | number, - vertical?: boolean, - allowCross?: boolean, - pushable?: boolean | number, -} - -export interface SliderBaseState { - handle: number | null, - recent: number, - bounds: number[] -} - -export class SliderBase extends React.Component<SliderBaseProps, SliderBaseState> { - private sliderElement: HTMLElement | undefined = void 0; - private handleElements: (HTMLElement | undefined)[] = []; - - state: SliderBaseState = { - handle: null, - recent: 0, - bounds: [0, 0], - }; - - constructor(props: SliderBaseProps) { - super(props); - - const { range, min, max } = props; - const initialValue = range ? Array.apply(null, Array(+range + 1)).map(() => min) : min; - const defaultValue = ('defaultValue' in props ? props.defaultValue : initialValue); - const value = (props.value !== undefined ? props.value : defaultValue); - - const bounds = (range ? value : [min, value]).map((v: number) => this.trimAlignValue(v)); - - let recent; - if (range && bounds[0] === bounds[bounds.length - 1] && bounds[0] === max) { - recent = 0; - } else { - recent = bounds.length - 1; - } - - this.state = { - handle: null, - recent, - bounds, - }; - } - - public static defaultProps: SliderBaseProps = { - prefixCls: 'molstar-slider-base', - className: '', - min: 0, - max: 100, - step: 1, - marks: {}, - handle: <Handle className='' vertical={false} offset={0} tipFormatter={v => v} value={0} index={0} />, - onBeforeChange: noop, - onChange: noop, - onAfterChange: noop, - tipFormatter: (value, index) => value, - included: true, - disabled: false, - dots: false, - range: false, - vertical: false, - allowCross: true, - pushable: false, - }; - - private dragOffset = 0; - private startPosition = 0; - private startValue = 0; - private _getPointsCache: any = void 0; - - componentWillReceiveProps(nextProps: SliderBaseProps) { - if (!('value' in nextProps || 'min' in nextProps || 'max' in nextProps)) return; - - const { bounds } = this.state; - if (nextProps.range) { - const value = nextProps.value || bounds; - const nextBounds = (value as number[]).map((v: number) => this.trimAlignValue(v, nextProps)); - if (nextBounds.every((v: number, i: number) => v === bounds[i])) return; - - this.setState({ bounds: nextBounds } as SliderBaseState); - if (bounds.some(v => this.isValueOutOfBounds(v, nextProps))) { - this.props.onChange!(nextBounds); - } - } else { - const value = nextProps.value !== undefined ? nextProps.value : bounds[1]; - const nextValue = this.trimAlignValue(value as number, nextProps); - if (nextValue === bounds[1] && bounds[0] === nextProps.min) return; - - this.setState({ bounds: [nextProps.min, nextValue] } as SliderBaseState); - if (this.isValueOutOfBounds(bounds[1], nextProps)) { - this.props.onChange!(nextValue); - } - } - } - - onChange(state: this['state']) { - const props = this.props; - const isNotControlled = !('value' in props); - if (isNotControlled) { - this.setState(state); - } else if (state.handle !== undefined) { - this.setState({ handle: state.handle } as SliderBaseState); - } - - const data = { ...this.state, ...(state as any) }; - const changedValue = props.range ? data.bounds : data.bounds[1]; - props.onChange!(changedValue); - } - - onMouseDown(e: MouseEvent) { - if (e.button !== 0) { return; } - - let position = getMousePosition(this.props.vertical!, e); - if (!this.isEventFromHandle(e)) { - this.dragOffset = 0; - } else { - const handlePosition = getHandleCenterPosition(this.props.vertical!, e.target as HTMLElement); - this.dragOffset = position - handlePosition; - position = handlePosition; - } - this.onStart(position); - this.addDocumentEvents('mouse'); - pauseEvent(e); - } - - onMouseMove(e: MouseEvent) { - const position = getMousePosition(this.props.vertical!, e); - this.onMove(e, position - this.dragOffset); - } - - onMove(e: MouseEvent | TouchEvent, position: number) { - pauseEvent(e); - const props = this.props; - const state = this.state; - - let diffPosition = position - this.startPosition; - diffPosition = this.props.vertical ? -diffPosition : diffPosition; - const diffValue = diffPosition / this.getSliderLength() * (props.max - props.min); - - const value = this.trimAlignValue(this.startValue + diffValue); - const oldValue = state.bounds[state.handle!]; - if (value === oldValue) return; - - const nextBounds = [...state.bounds]; - nextBounds[state.handle!] = value; - let nextHandle = state.handle!; - if (props.pushable !== false) { - const originalValue = state.bounds[nextHandle]; - this.pushSurroundingHandles(nextBounds, nextHandle, originalValue); - } else if (props.allowCross) { - nextBounds.sort((a, b) => a - b); - nextHandle = nextBounds.indexOf(value); - } - this.onChange({ - handle: nextHandle, - bounds: nextBounds, - } as SliderBaseState); - } - - onStart(position: number) { - const props = this.props; - props.onBeforeChange!(this.getValue()); - - const value = this.calcValueByPos(position); - this.startValue = value; - this.startPosition = position; - - const state = this.state; - const { bounds } = state; - - let valueNeedChanging = 1; - if (this.props.range) { - let closestBound = 0; - for (let i = 1; i < bounds.length - 1; ++i) { - if (value > bounds[i]) { closestBound = i; } - } - if (Math.abs(bounds[closestBound + 1] - value) < Math.abs(bounds[closestBound] - value)) { - closestBound = closestBound + 1; - } - valueNeedChanging = closestBound; - - const isAtTheSamePoint = (bounds[closestBound + 1] === bounds[closestBound]); - if (isAtTheSamePoint) { - valueNeedChanging = state.recent; - } - - if (isAtTheSamePoint && (value !== bounds[closestBound + 1])) { - valueNeedChanging = value < bounds[closestBound + 1] ? closestBound : closestBound + 1; - } - } - - this.setState({ - handle: valueNeedChanging, - recent: valueNeedChanging, - } as SliderBaseState); - - const oldValue = state.bounds[valueNeedChanging]; - if (value === oldValue) return; - - const nextBounds = [...state.bounds]; - nextBounds[valueNeedChanging] = value; - this.onChange({ bounds: nextBounds } as SliderBaseState); - } - - onTouchMove(e: TouchEvent) { - if (isNotTouchEvent(e)) { - this.end('touch'); - return; - } - - const position = getTouchPosition(this.props.vertical!, e); - this.onMove(e, position - this.dragOffset); - } - - onTouchStart(e: TouchEvent) { - if (isNotTouchEvent(e)) return; - - let position = getTouchPosition(this.props.vertical!, e); - if (!this.isEventFromHandle(e)) { - this.dragOffset = 0; - } else { - const handlePosition = getHandleCenterPosition(this.props.vertical!, e.target as HTMLElement); - this.dragOffset = position - handlePosition; - position = handlePosition; - } - this.onStart(position); - this.addDocumentEvents('touch'); - pauseEvent(e); - } - - /** - * Returns an array of possible slider points, taking into account both - * `marks` and `step`. The result is cached. - */ - getPoints() { - const { marks, step, min, max } = this.props; - const cache = this._getPointsCache; - if (!cache || cache.marks !== marks || cache.step !== step) { - const pointsObject = { ...marks }; - if (step !== null) { - for (let point = min; point <= max; point += step!) { - pointsObject[point] = point; - } - } - const points = Object.keys(pointsObject).map(parseFloat); - points.sort((a, b) => a - b); - this._getPointsCache = { marks, step, points }; - } - return this._getPointsCache.points; - } - - getPrecision(step: number) { - const stepString = step.toString(); - let precision = 0; - if (stepString.indexOf('.') >= 0) { - precision = stepString.length - stepString.indexOf('.') - 1; - } - return precision; - } - - getSliderLength() { - const slider = this.sliderElement; - if (!slider) { - return 0; - } - - return this.props.vertical ? slider.clientHeight : slider.clientWidth; - } - - getSliderStart() { - const slider = this.sliderElement as HTMLElement; - const rect = slider.getBoundingClientRect(); - - return this.props.vertical ? rect.top : rect.left; - } - - getValue(): number { - const { bounds } = this.state; - return (this.props.range ? bounds : bounds[1]) as number; - } - - private eventHandlers = { - 'touchmove': (e: TouchEvent) => this.onTouchMove(e), - 'touchend': (e: TouchEvent) => this.end('touch'), - 'mousemove': (e: MouseEvent) => this.onMouseMove(e), - 'mouseup': (e: MouseEvent) => this.end('mouse'), - } - - addDocumentEvents(type: 'touch' | 'mouse') { - if (type === 'touch') { - document.addEventListener('touchmove', this.eventHandlers.touchmove); - document.addEventListener('touchend', this.eventHandlers.touchend); - } else if (type === 'mouse') { - document.addEventListener('mousemove', this.eventHandlers.mousemove); - document.addEventListener('mouseup', this.eventHandlers.mouseup); - } - } - - calcOffset(value: number) { - const { min, max } = this.props; - const ratio = (value - min) / (max - min); - return ratio * 100; - } - - calcValue(offset: number) { - const { vertical, min, max } = this.props; - const ratio = Math.abs(offset / this.getSliderLength()); - const value = vertical ? (1 - ratio) * (max - min) + min : ratio * (max - min) + min; - return value; - } - - calcValueByPos(position: number) { - const pixelOffset = position - this.getSliderStart(); - const nextValue = this.trimAlignValue(this.calcValue(pixelOffset)); - return nextValue; - } - - end(type: 'mouse' | 'touch') { - this.removeEvents(type); - this.props.onAfterChange!(this.getValue()); - this.setState({ handle: null } as SliderBaseState); - } - - isEventFromHandle(e: Event) { - for (const h of this.handleElements) { - if (h === e.target) return true; - } - return false; - - // return this.state.bounds.some((x, i) => e.target - - // ( - // //this.handleElements[i] && e.target === ReactDOM.findDOMNode(this.handleElements[i]) - // )); - } - - isValueOutOfBounds(value: number, props: SliderBaseProps) { - return value < props.min || value > props.max; - } - - pushHandle(bounds: number[], handle: number, direction: number, amount: number) { - const originalValue = bounds[handle]; - let currentValue = bounds[handle]; - while (direction * (currentValue - originalValue) < amount) { - if (!this.pushHandleOnePoint(bounds, handle, direction)) { - // can't push handle enough to create the needed `amount` gap, so we - // revert its position to the original value - bounds[handle] = originalValue; - return false; - } - currentValue = bounds[handle]; - } - // the handle was pushed enough to create the needed `amount` gap - return true; - } - - pushHandleOnePoint(bounds: number[], handle: number, direction: number) { - const points = this.getPoints(); - const pointIndex = points.indexOf(bounds[handle]); - const nextPointIndex = pointIndex + direction; - if (nextPointIndex >= points.length || nextPointIndex < 0) { - // reached the minimum or maximum available point, can't push anymore - return false; - } - const nextHandle = handle + direction; - const nextValue = points[nextPointIndex]; - const { pushable: threshold } = this.props; - const diffToNext = direction * (bounds[nextHandle] - nextValue); - if (!this.pushHandle(bounds, nextHandle, direction, +threshold! - diffToNext)) { - // couldn't push next handle, so we won't push this one either - return false; - } - // push the handle - bounds[handle] = nextValue; - return true; - } - - pushSurroundingHandles(bounds: number[], handle: number, originalValue: number) { - const { pushable: threshold } = this.props; - const value = bounds[handle]; - - let direction = 0; - if (bounds[handle + 1] - value < threshold!) { - direction = +1; - } else if (value - bounds[handle - 1] < threshold!) { - direction = -1; - } - - if (direction === 0) { return; } - - const nextHandle = handle + direction; - const diffToNext = direction * (bounds[nextHandle] - value); - if (!this.pushHandle(bounds, nextHandle, direction, +threshold! - diffToNext)) { - // revert to original value if pushing is impossible - bounds[handle] = originalValue; - } - } - - removeEvents(type: 'touch' | 'mouse') { - if (type === 'touch') { - document.removeEventListener('touchmove', this.eventHandlers.touchmove); - document.removeEventListener('touchend', this.eventHandlers.touchend); - } else if (type === 'mouse') { - document.removeEventListener('mousemove', this.eventHandlers.mousemove); - document.removeEventListener('mouseup', this.eventHandlers.mouseup); - } - } - - trimAlignValue(v: number, nextProps?: SliderBaseProps) { - const { handle, bounds } = (this.state || {}) as this['state']; - const { marks, step, min, max, allowCross } = { ...this.props, ...(nextProps || {}) } as SliderBaseProps; - - let val = v; - if (val <= min) { - val = min; - } - if (val >= max) { - val = max; - } - /* eslint-disable eqeqeq */ - if (!allowCross && handle != null && handle > 0 && val <= bounds[handle - 1]) { - val = bounds[handle - 1]; - } - if (!allowCross && handle != null && handle < bounds.length - 1 && val >= bounds[handle + 1]) { - val = bounds[handle + 1]; - } - /* eslint-enable eqeqeq */ - - const points = Object.keys(marks).map(parseFloat); - if (step !== null) { - const closestStep = (Math.round((val - min) / step!) * step!) + min; - points.push(closestStep); - } - - const diffs = points.map((point) => Math.abs(val - point)); - const closestPoint = points[diffs.indexOf(Math.min.apply(Math, diffs))]; - - return step !== null ? parseFloat(closestPoint.toFixed(this.getPrecision(step!))) : closestPoint; - } - - render() { - const { - handle, - bounds, - } = this.state; - const { - className, - prefixCls, - disabled, - vertical, - dots, - included, - range, - step, - marks, - max, min, - tipFormatter, - children, - } = this.props; - - const customHandle = this.props.handle; - - const offsets = bounds.map(v => this.calcOffset(v)); - - const handleClassName = `${prefixCls}-handle`; - - const handlesClassNames = bounds.map((v, i) => classNames({ - [handleClassName]: true, - [`${handleClassName}-${i + 1}`]: true, - [`${handleClassName}-lower`]: i === 0, - [`${handleClassName}-upper`]: i === bounds.length - 1, - })); - - const isNoTip = (step === null) || (tipFormatter === null); - - const commonHandleProps = { - prefixCls, - noTip: isNoTip, - tipFormatter, - vertical, - }; - - this.handleElements = []; - const handles = bounds.map((v, i) => React.cloneElement(customHandle!, { - ...commonHandleProps, - className: handlesClassNames[i], - value: v, - offset: offsets[i], - dragging: handle === i, - index: i, - key: i, - ref: (h: any) => this.handleElements.push(h) //`handle-${i}`, - })); - if (!range) { handles.shift(); } - - const isIncluded = included || range; - - const tracks: JSX.Element[] = []; - // for (let i = 1; i < bounds.length; ++i) { - // const trackClassName = classNames({ - // [`${prefixCls}-track`]: true, - // [`${prefixCls}-track-${i}`]: true, - // }); - // tracks.push( - // <Track className={trackClassName} vertical={vertical} included={isIncluded} - // offset={offsets[i - 1]} length={offsets[i] - offsets[i - 1]} key={i} - // /> - // ); - // } - - const sliderClassName = classNames({ - [prefixCls!]: true, - [`${prefixCls}-with-marks`]: Object.keys(marks).length, - [`${prefixCls}-disabled`]: disabled!, - [`${prefixCls}-vertical`]: this.props.vertical!, - [className!]: !!className, - }); - - return ( - <div ref={e => this.sliderElement = e!} className={sliderClassName} - onTouchStart={disabled ? noop : this.onTouchStart.bind(this)} - onMouseDown={disabled ? noop : this.onMouseDown.bind(this)} - > - <div className={`${prefixCls}-rail`} /> - {tracks} - <Steps prefixCls={prefixCls} vertical={vertical} marks={marks} dots={dots} step={step} - included={isIncluded} lowerBound={bounds[0]} - upperBound={bounds[bounds.length - 1]} max={max} min={min} - /> - {handles} - <Marks className={`${prefixCls}-mark`} vertical={vertical!} marks={marks} - included={isIncluded!} lowerBound={bounds[0]} - upperBound={bounds[bounds.length - 1]} max={max} min={min} - /> - {children} - </div> - ); - } -} - -export interface HandleProps { - className: string, - vertical: boolean, - offset: number, - tipFormatter: (v: number, index: number) => any, - value: number, - index: number, -} - -interface MarksProps { - className: string, - vertical: boolean, - marks: any, - included: boolean | number, - upperBound: number, - lowerBound: number, - max: number, - min: number -} -const Marks = ({ className, vertical, marks, included, upperBound, lowerBound, max, min }: MarksProps) => { - const marksKeys = Object.keys(marks); - const marksCount = marksKeys.length; - const unit = 100 / (marksCount - 1); - const markWidth = unit * 0.9; - - const range = max - min; - const elements = marksKeys.map(parseFloat).sort((a, b) => a - b).map((point) => { - const isActived = (!included && point === upperBound) || - (included && point <= upperBound && point >= lowerBound); - const markClassName = classNames({ - [`${className}-text`]: true, - [`${className}-text-active`]: isActived, - }); - - const bottomStyle = { - // height: markWidth + '%', - marginBottom: '-50%', - bottom: `${(point - min) / range * 100}%`, - }; - - const leftStyle = { - width: `${markWidth}%`, - marginLeft: `${-markWidth / 2}%`, - left: `${(point - min) / range * 100}%`, - }; - - const style = vertical ? bottomStyle : leftStyle; - - const markPoint = marks[point]; - const markPointIsObject = typeof markPoint === 'object' && !React.isValidElement(markPoint); - const markLabel = markPointIsObject ? markPoint.label : markPoint; - const markStyle = markPointIsObject ? { ...style, ...markPoint.style } : style; - return (<span className={markClassName} style={markStyle} key={point}> - {markLabel} - </span>); - }); - - return <div className={className}>{elements}</div>; -}; - -function calcPoints(vertical: boolean, marks: any, dots: boolean, step: number, min: number, max: number) { - const points = Object.keys(marks).map(parseFloat); - if (dots) { - for (let i = min; i <= max; i = i + step) { - if (points.indexOf(i) >= 0) continue; - points.push(i); - } - } - return points; -} - -const Steps = ({ prefixCls, vertical, marks, dots, step, included, - lowerBound, upperBound, max, min }: any) => { - const range = max - min; - const elements = calcPoints(vertical, marks, dots, step, min, max).map((point) => { - const offset = `${Math.abs(point - min) / range * 100}%`; - const style = vertical ? { bottom: offset } : { left: offset }; - - const isActived = (!included && point === upperBound) || - (included && point <= upperBound && point >= lowerBound); - const pointClassName = classNames({ - [`${prefixCls}-dot`]: true, - [`${prefixCls}-dot-active`]: isActived, - }); - - return <span className={pointClassName} style={style} key={point} />; - }); - - return <div className={`${prefixCls}-step`}>{elements}</div>; -}; \ No newline at end of file diff --git a/src/mol-app/ui/entity/tree.tsx b/src/mol-app/ui/entity/tree.tsx deleted file mode 100644 index d83e0a9da6d726f363dddb5e52820e71251fd2df..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/entity/tree.tsx +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { EntityTreeController } from '../../controller/entity/tree'; -import { Controller } from '../../controller/controller'; -import { AnyEntity, RootEntity } from 'mol-view/state/entity'; -import { AnyTransform, SpacefillUpdate, UrlToData, DataToCif, FileToData, CifToMmcif, MmcifToModel, ModelToStructure, StructureToSpacefill, MmcifFileToSpacefill, StructureCenter, StructureToBallAndStick, DistanceRestraintUpdate, CartoonUpdate, BallAndStickUpdate, BackboneUpdate, MmcifUrlToSpacefill, CarbohydrateUpdate } from 'mol-view/state/transform'; - -function getTransforms(entity: AnyEntity): AnyTransform[] { - const transforms: AnyTransform[] = [] - switch (entity.kind) { - case 'root': - transforms.push(MmcifFileToSpacefill, MmcifUrlToSpacefill) - break; - case 'url': - transforms.push(UrlToData) - break; - case 'file': - transforms.push(FileToData) - break; - case 'data': - transforms.push(DataToCif) - break; - case 'cif': - transforms.push(CifToMmcif) - break; - case 'mmcif': - transforms.push(MmcifToModel) - break; - case 'model': - transforms.push(ModelToStructure) - break; - case 'structure': - transforms.push(StructureToSpacefill, StructureToBallAndStick, StructureCenter) - break; - case 'spacefill': - transforms.push(SpacefillUpdate) - break; - case 'ballandstick': - transforms.push(BallAndStickUpdate) - break; - case 'distancerestraint': - transforms.push(DistanceRestraintUpdate) - break; - case 'backbone': - transforms.push(BackboneUpdate) - break; - case 'cartoon': - transforms.push(CartoonUpdate) - break; - case 'carbohydrate': - transforms.push(CarbohydrateUpdate) - break; - } - return transforms -} - -export class Entity extends View<Controller<any>, {}, { entity: AnyEntity}> { - render() { - const entity = this.props.entity - - return <div className='molstar-entity-tree-entry'> - <div className='molstar-entity-tree-entry-body'> - <div className='molstar-entity-tree-entry-label-wrap'> - <button - className='molstar-entity-tree-entry-label' - onClick={() => { - console.log(entity) - this.controller.context.currentEntity.next(entity) - this.controller.context.currentTransforms.next(getTransforms(entity)) - }} - > - <span>{entity.id} - {entity.kind}</span> - </button> - </div> - </div> - </div>; - } -} - -export class EntityTree extends View<EntityTreeController, {}, {}> { - render() { - const entities: JSX.Element[] = [] - const state = this.controller.state.getValue() - if (state) { - state.entities.forEach(e => { - entities.push( - <div key={e.id}> - <Entity controller={this.controller} entity={e}></Entity> - </div> - ) - }) - } - - return <div className='molstar-entity-tree'> - <div className='molstar-entity-tree-root'> - <Entity controller={this.controller} entity={RootEntity}></Entity> - </div> - <div className='molstar-entity-tree-children'> - <div>{entities}</div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/layout.tsx b/src/mol-app/ui/layout.tsx deleted file mode 100644 index df5184a84a82e6396e471ce069fb74ba2c310e9d..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/layout.tsx +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import * as React from 'react' -import { LayoutController, LayoutTarget, LayoutRegion, CollapsedControlsLayout } from '../controller/layout'; -import { View } from './view'; - -export class Layout extends View<LayoutController, { }, { }> { - - private renderTarget(target: LayoutTarget) { - const statics: any[] = []; - const scrollable: any[] = []; - - for (let c of target.components) { - if (c.isStatic) statics.push(<c.view key={c.key} controller={c.controller} />); - else scrollable.push(<c.view key={c.key} controller={c.controller} />); - } - - return <div key={target.cssClass} className={'molstar-layout-region molstar-layout-' + target.cssClass}> - { statics.length ? <div className='molstar-layout-static'>{statics}</div> : void 0 } - { scrollable.length ? <div className='molstar-layout-scrollable'>{scrollable}</div> : void 0 } - </div>; - } - - private updateTarget(name: string, regionType: LayoutRegion, layout: { regions: any[], layoutClass: string }) { - const state = this.controller.latestState; - const regionStates = state.regionStates; - const region = this.controller.targets[regionType]; - let show: boolean; - - if (state.hideControls) { - show = regionStates !== void 0 && regionStates[regionType] === 'Sticky' && region.components.length > 0; - } else if (regionStates && regionStates[regionType] === 'Hidden') { - show = false; - } else { - show = region.components.length > 0; - } - - if (show) { - layout.regions.push(this.renderTarget(region)); - } else { - layout.layoutClass += ' molstar-layout-hide-' + name; - } - } - - render() { - let layoutClass = ''; - - const state = this.controller.latestState; - let layoutType: string; - - if (state.isExpanded) { - layoutType = 'molstar-layout-expanded'; - } else { - layoutType = 'molstar-layout-standard '; - switch (state.collapsedControlsLayout) { - case CollapsedControlsLayout.Outside: layoutType += 'molstar-layout-standard-outside'; break; - case CollapsedControlsLayout.Landscape: layoutType += 'molstar-layout-standard-landscape'; break; - case CollapsedControlsLayout.Portrait: layoutType += 'molstar-layout-standard-portrait'; break; - default: layoutType += 'molstar-layout-standard-outside'; break; - } - } - - const targets = this.controller.targets; - const regions = [this.renderTarget(targets[LayoutRegion.Main])]; - - const layout = { regions, layoutClass }; - this.updateTarget('top', LayoutRegion.Top, layout); - this.updateTarget('right', LayoutRegion.Right, layout); - this.updateTarget('bottom', LayoutRegion.Bottom, layout); - this.updateTarget('left', LayoutRegion.Left, layout); - layoutClass = layout.layoutClass; - - let root = targets[LayoutRegion.Root].components.map(c => <c.view key={c.key} controller={c.controller} />); - - return <div className='molstar-plugin'> - <div className={'molstar-plugin-content ' + layoutType}> - <div className={layoutClass}> - {regions} - {root} - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/misc/jobs.tsx b/src/mol-app/ui/misc/jobs.tsx deleted file mode 100644 index 6090da945a97d077f8d000bd1311d820fc2ca527..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/misc/jobs.tsx +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import * as React from 'react' -import { JobInfo, JobsController } from '../../controller/misc/jobs'; -import { Button } from '../controls/common'; -import { View } from '../view'; - -class JobState extends React.Component<{ info: JobInfo, isSmall?: boolean }, {}> { - render() { - const info = this.props.info; - return <div className='molstar-task-state'> - <div> - { info.abort ? <Button onClick={() => info.abort!.call(null) } style='remove' - icon='abort' title='Abort' customClass='molstar-btn-icon' - /> : void 0 } - <div> - {info.name}: {info.message} - </div> - </div> - </div>; - } -} - -export class Overlay extends View<JobsController, {}, {}> { - render() { - const state = this.controller.latestState; - - if (!Object.keys(state.jobs).length) return <div className='molstar-empty-control' /> - - const jobs: any[] = []; - Object.keys(state.jobs).forEach(k => jobs.push(<JobState key={k} info={state.jobs[parseInt(k)]} />)); - - return <div className='molstar-overlay'> - <div className='molstar-overlay-background' /> - <div className='molstar-overlay-content-wrap'> - <div className='molstar-overlay-content'> - <div> - {jobs} - </div> - </div> - </div> - </div>; - } -} - -export class BackgroundJobs extends View<JobsController, {}, {}> { - render() { - const state = this.controller.latestState; - - if (!Object.keys(state.jobs).length) return <div className='molstar-empty-control' /> - - const jobs: any[] = []; - Object.keys(state.jobs).forEach(k => jobs.push(<JobState key={k} info={state.jobs[parseInt(k)]} isSmall={true} />)); - - return <div className='molstar-background-jobs'> - {jobs} - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/misc/log.tsx b/src/mol-app/ui/misc/log.tsx deleted file mode 100644 index 803d86f70ea25417a5f95a51daebac54561faa51..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/misc/log.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import * as React from 'react' -import { View } from '../view'; -import { LogController } from '../../controller/misc/log'; -import { CommonEvents } from '../../event/basic'; -import { formatTime } from 'mol-util'; -import { Logger } from '../../service/logger'; - -export class Log extends View<LogController, {}, {}> { - - private wrapper: HTMLDivElement | undefined = void 0; - - componentWillMount() { - super.componentWillMount(); - this.subscribe(CommonEvents.LayoutChanged.getStream(this.controller.context), () => this.scrollToBottom()); - } - - componentDidUpdate() { - this.scrollToBottom(); - } - - private scrollToBottom() { - const log = this.wrapper; - if (log) log.scrollTop = log.scrollHeight - log.clientHeight - 1; - } - - render() { - const entries = this.controller.latestState.entries; - - return <div className='molstar-log-wrap'> - <div className='molstar-log' ref={log => this.wrapper = log!}> - <ul className='molstar-list-unstyled'> - {entries.map((entry, i, arr) => { - - let label: JSX.Element; - let e = entry!; - switch (e.type) { - case Logger.EntryType.Error: - label = <span className='label label-danger'>Error</span>; - break; - case Logger.EntryType.Warning: - label = <span className='label label-warning'>Warning</span>; - break; - case Logger.EntryType.Info: - label = <span className='label label-info'>Info</span>; - break; - default: - label = <span></span> - } - - let t = formatTime(e.timestamp); - return <li key={i}> - <div className={'molstar-log-entry-badge molstar-log-entry-' + Logger.EntryType[e.type].toLowerCase()} /> - {label} - <div className='molstar-log-timestamp'>{t}</div> - <div className='molstar-log-entry'>{e.message}</div> - </li>; - }) } - </ul> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/backbone.tsx b/src/mol-app/ui/transform/backbone.tsx deleted file mode 100644 index 93a4a3392618673ea30514e515ef0d8f3dff0d6c..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/backbone.tsx +++ /dev/null @@ -1,244 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { Toggle } from '../controls/common'; -import { BackboneEntity } from 'mol-view/state/entity'; -import { BackboneUpdate } from 'mol-view/state/transform' -import { StateContext } from 'mol-view/state/context'; -import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme/color'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { Color, ColorNames } from 'mol-util/color'; -import { Slider } from '../controls/slider'; -import { Unit } from 'mol-model/structure'; -import { VisualQuality } from 'mol-geo/geometry/geometry'; - -interface BackboneState { - doubleSided: boolean - flipSided: boolean - flatShaded: boolean - detail: number - colorTheme: ColorThemeProps - colorValue: Color - sizeTheme: SizeThemeProps - visible: boolean - alpha: number - depthMask: boolean - useFog: boolean - quality: VisualQuality - unitKinds: Unit.Kind[] - radialSegments: number -} - -export class Backbone extends View<Controller<any>, BackboneState, { transform: BackboneUpdate, entity: BackboneEntity, ctx: StateContext }> { - state = { - doubleSided: true, - flipSided: false, - flatShaded: false, - detail: 2, - colorTheme: { name: 'element-symbol' } as ColorThemeProps, - colorValue: Color(0x000000), - sizeTheme: { name: 'uniform', factor: 1 } as SizeThemeProps, - visible: true, - alpha: 1, - depthMask: true, - useFog: true, - quality: 'auto' as VisualQuality, - unitKinds: [] as Unit.Kind[], - radialSegments: 16 - } - - componentWillMount() { - this.setState({ ...this.state, ...this.props.entity.value.props }) - } - - update(state?: Partial<BackboneState>) { - const { transform, entity, ctx } = this.props - const newState = { ...this.state, ...state } - this.setState(newState) - transform.apply(ctx, entity, newState) - } - - render() { - const { transform } = this.props - - const qualityOptions = ['auto', 'custom', 'highest', 'high', 'medium', 'low', 'lowest'].map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const sphereDetailOptions = [0, 1, 2, 3].map((value, idx) => { - return <option key={value} value={value}>{value.toString()}</option> - }) - - const colorThemeOptions = ColorThemeNames.map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const colorValueOptions = Object.keys(ColorNames).map((name, idx) => { - return <option key={name} value={(ColorNames as any)[name]}>{name}</option> - }) - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={() => this.update()} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <span>Quality</span> - <div> - <select - className='molstar-form-control' - value={this.state.quality} - onChange={(e) => this.update({ quality: e.target.value as VisualQuality })} - > - {qualityOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Sphere detail</span> - <div> - <select - className='molstar-form-control' - value={this.state.detail} - onChange={(e) => this.update({ detail: parseInt(e.target.value) })} - > - {sphereDetailOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color theme</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorTheme.name} - onChange={(e) => { - this.update({ - colorTheme: { - name: e.target.value as ColorThemeName, - value: this.state.colorValue - } - }) - }} - > - {colorThemeOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color value</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorValue} - onChange={(e) => { - const colorValue = Color(parseInt(e.target.value)) - this.update({ - colorTheme: { - name: 'uniform', - value: colorValue - }, - colorValue - }) - }} - > - {colorValueOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.visible} - label='Visibility' - onChange={value => this.update({ visible: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.depthMask} - label='Depth write' - onChange={value => this.update({ depthMask: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.doubleSided} - label='Double sided' - onChange={value => this.update({ doubleSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flipSided} - label='Flip sided' - onChange={value => this.update({ flipSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flatShaded} - label='Flat shaded' - onChange={value => this.update({ flatShaded: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.alpha} - label='Opacity' - min={0} - max={1} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ alpha: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.sizeTheme.factor || 1} - label='Size factor' - min={0.1} - max={3} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ - sizeTheme: { ...this.state.sizeTheme, factor: value } - })} - /> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/ball-and-stick.tsx b/src/mol-app/ui/transform/ball-and-stick.tsx deleted file mode 100644 index 38320c2b07341ef93674381c3cb52718b9008af0..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/ball-and-stick.tsx +++ /dev/null @@ -1,234 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { Toggle } from '../controls/common'; -import { DistanceRestraintEntity } from 'mol-view/state/entity'; -import { DistanceRestraintUpdate } from 'mol-view/state/transform' -import { StateContext } from 'mol-view/state/context'; -import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme/color'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { Color, ColorNames } from 'mol-util/color'; -import { Slider } from '../controls/slider'; -import { Unit } from 'mol-model/structure'; -import { VisualQuality } from 'mol-geo/geometry/geometry'; - -interface BallAndStickState { - doubleSided: boolean - flipSided: boolean - flatShaded: boolean - colorTheme: ColorThemeProps - colorValue: Color - sizeTheme: SizeThemeProps - visible: boolean - alpha: number - depthMask: boolean - useFog: boolean - quality: VisualQuality - linkScale: number - linkSpacing: number - linkRadius: number - radialSegments: number - detail: number - unitKinds: Unit.Kind[] -} - -export class BallAndStick extends View<Controller<any>, BallAndStickState, { transform: DistanceRestraintUpdate, entity: DistanceRestraintEntity, ctx: StateContext }> { - state = { - doubleSided: true, - flipSided: false, - flatShaded: false, - colorTheme: { name: 'element-symbol' } as ColorThemeProps, - colorValue: Color(0x000000), - sizeTheme: { name: 'uniform', value: 0.15 } as SizeThemeProps, - visible: true, - alpha: 1, - depthMask: true, - useFog: true, - quality: 'auto' as VisualQuality, - linkScale: 0.4, - linkSpacing: 1, - linkRadius: 0.25, - radialSegments: 16, - detail: 1, - unitKinds: [] as Unit.Kind[] - } - - componentWillMount() { - this.setState({ ...this.state, ...this.props.entity.value.props }) - } - - update(state?: Partial<BallAndStickState>) { - const { transform, entity, ctx } = this.props - const newState = { ...this.state, ...state } - this.setState(newState) - transform.apply(ctx, entity, newState) - } - - render() { - const { transform } = this.props - - const qualityOptions = ['auto', 'custom', 'highest', 'high', 'medium', 'low', 'lowest'].map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const colorThemeOptions = ColorThemeNames.map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const colorValueOptions = Object.keys(ColorNames).map((name, idx) => { - return <option key={name} value={(ColorNames as any)[name]}>{name}</option> - }) - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={() => this.update()} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <span>Quality</span> - <div> - <select - className='molstar-form-control' - value={this.state.quality} - onChange={(e) => this.update({ quality: e.target.value as VisualQuality })} - > - {qualityOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color theme</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorTheme.name} - onChange={(e) => { - this.update({ - colorTheme: { - name: e.target.value as ColorThemeName, - value: this.state.colorValue - } - }) - }} - > - {colorThemeOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color value</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorValue} - onChange={(e) => { - const colorValue = Color(parseInt(e.target.value)) - this.update({ - colorTheme: { - name: 'uniform', - value: colorValue - }, - colorValue - }) - }} - > - {colorValueOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.visible} - label='Visibility' - onChange={value => this.update({ visible: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.depthMask} - label='Depth write' - onChange={value => this.update({ depthMask: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.doubleSided} - label='Double sided' - onChange={value => this.update({ doubleSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flipSided} - label='Flip sided' - onChange={value => this.update({ flipSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flatShaded} - label='Flat shaded' - onChange={value => this.update({ flatShaded: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.alpha} - label='Opacity' - min={0} - max={1} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ alpha: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.sizeTheme.factor || 1} - label='Size factor' - min={0.1} - max={3} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ - sizeTheme: { ...this.state.sizeTheme, factor: value } - })} - /> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/carbohydrate.tsx b/src/mol-app/ui/transform/carbohydrate.tsx deleted file mode 100644 index e725131474ef63d60261eab264c4c925a3f8ad31..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/carbohydrate.tsx +++ /dev/null @@ -1,250 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { Toggle } from '../controls/common'; -import { CarbohydrateEntity } from 'mol-view/state/entity'; -import { CarbohydrateUpdate } from 'mol-view/state/transform' -import { StateContext } from 'mol-view/state/context'; -import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme/color'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { Color, ColorNames } from 'mol-util/color'; -import { Slider } from '../controls/slider'; -import { Unit } from 'mol-model/structure'; -import { VisualQuality } from 'mol-geo/geometry/geometry'; - -interface CarbohydrateState { - doubleSided: boolean - flipSided: boolean - flatShaded: boolean - detail: number - colorTheme: ColorThemeProps - colorValue: Color - sizeTheme: SizeThemeProps - visible: boolean - alpha: number - depthMask: boolean - useFog: boolean - quality: VisualQuality - unitKinds: Unit.Kind[] - linkScale: number - linkSpacing: number - linkRadius: number - radialSegments: number -} - -export class Carbohydrate extends View<Controller<any>, CarbohydrateState, { transform: CarbohydrateUpdate, entity: CarbohydrateEntity, ctx: StateContext }> { - state = { - doubleSided: true, - flipSided: false, - flatShaded: false, - detail: 2, - colorTheme: { name: 'element-symbol' } as ColorThemeProps, - colorValue: Color(0x000000), - sizeTheme: { name: 'uniform', factor: 1 } as SizeThemeProps, - visible: true, - alpha: 1, - depthMask: true, - useFog: true, - quality: 'auto' as VisualQuality, - unitKinds: [] as Unit.Kind[], - linkScale: 0.4, - linkSpacing: 1, - linkRadius: 0.25, - radialSegments: 16 - } - - componentWillMount() { - this.setState({ ...this.state, ...this.props.entity.value.props }) - } - - update(state?: Partial<CarbohydrateState>) { - const { transform, entity, ctx } = this.props - const newState = { ...this.state, ...state } - this.setState(newState) - transform.apply(ctx, entity, newState) - } - - render() { - const { transform } = this.props - - const qualityOptions = ['auto', 'custom', 'highest', 'high', 'medium', 'low', 'lowest'].map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const sphereDetailOptions = [0, 1, 2, 3].map((value, idx) => { - return <option key={value} value={value}>{value.toString()}</option> - }) - - const colorThemeOptions = ColorThemeNames.map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const colorValueOptions = Object.keys(ColorNames).map((name, idx) => { - return <option key={name} value={(ColorNames as any)[name]}>{name}</option> - }) - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={() => this.update()} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <span>Quality</span> - <div> - <select - className='molstar-form-control' - value={this.state.quality} - onChange={(e) => this.update({ quality: e.target.value as VisualQuality })} - > - {qualityOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Sphere detail</span> - <div> - <select - className='molstar-form-control' - value={this.state.detail} - onChange={(e) => this.update({ detail: parseInt(e.target.value) })} - > - {sphereDetailOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color theme</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorTheme.name} - onChange={(e) => { - this.update({ - colorTheme: { - name: e.target.value as ColorThemeName, - value: this.state.colorValue - } - }) - }} - > - {colorThemeOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color value</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorValue} - onChange={(e) => { - const colorValue = Color(parseInt(e.target.value)) - this.update({ - colorTheme: { - name: 'uniform', - value: colorValue - }, - colorValue - }) - }} - > - {colorValueOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.visible} - label='Visibility' - onChange={value => this.update({ visible: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.depthMask} - label='Depth write' - onChange={value => this.update({ depthMask: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.doubleSided} - label='Double sided' - onChange={value => this.update({ doubleSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flipSided} - label='Flip sided' - onChange={value => this.update({ flipSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flatShaded} - label='Flat shaded' - onChange={value => this.update({ flatShaded: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.alpha} - label='Opacity' - min={0} - max={1} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ alpha: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.sizeTheme.factor || 1} - label='Size factor' - min={0.1} - max={3} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ - sizeTheme: { ...this.state.sizeTheme, factor: value } - })} - /> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/cartoon.tsx b/src/mol-app/ui/transform/cartoon.tsx deleted file mode 100644 index 994934214126b6fbf9909791a65ac5777b883fdd..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/cartoon.tsx +++ /dev/null @@ -1,278 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { Toggle } from '../controls/common'; -import { CartoonEntity } from 'mol-view/state/entity'; -import { CartoonUpdate } from 'mol-view/state/transform' -import { StateContext } from 'mol-view/state/context'; -import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme/color'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { Color, ColorNames } from 'mol-util/color'; -import { Slider } from '../controls/slider'; -import { Unit } from 'mol-model/structure'; -import { VisualQuality } from 'mol-geo/geometry/geometry'; - -interface CartoonState { - doubleSided: boolean - flipSided: boolean - flatShaded: boolean - detail: number - colorTheme: ColorThemeProps - colorValue: Color - sizeTheme: SizeThemeProps - visible: boolean - alpha: number - depthMask: boolean - useFog: boolean - quality: VisualQuality - unitKinds: Unit.Kind[] - linearSegments: number - radialSegments: number - aspectRatio: number - arrowFactor: number -} - -export class Cartoon extends View<Controller<any>, CartoonState, { transform: CartoonUpdate, entity: CartoonEntity, ctx: StateContext }> { - state = { - doubleSided: true, - flipSided: false, - flatShaded: false, - detail: 2, - colorTheme: { name: 'element-symbol' } as ColorThemeProps, - colorValue: Color(0x000000), - sizeTheme: { name: 'uniform', value: 0.13, factor: 1 } as SizeThemeProps, - visible: true, - alpha: 1, - depthMask: true, - useFog: true, - quality: 'auto' as VisualQuality, - unitKinds: [] as Unit.Kind[], - linearSegments: 8, - radialSegments: 12, - aspectRatio: 8, - arrowFactor: 1.5 - } - - componentWillMount() { - this.setState({ ...this.state, ...this.props.entity.value.props }) - } - - update(state?: Partial<CartoonState>) { - const { transform, entity, ctx } = this.props - const newState = { ...this.state, ...state } - this.setState(newState) - transform.apply(ctx, entity, newState) - } - - render() { - const { transform } = this.props - - const qualityOptions = ['auto', 'custom', 'highest', 'high', 'medium', 'low', 'lowest'].map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const sphereDetailOptions = [0, 1, 2, 3].map((value, idx) => { - return <option key={value} value={value}>{value.toString()}</option> - }) - - const colorThemeOptions = ColorThemeNames.map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const colorValueOptions = Object.keys(ColorNames).map((name, idx) => { - return <option key={name} value={(ColorNames as any)[name]}>{name}</option> - }) - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={() => this.update()} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <span>Quality</span> - <div> - <select - className='molstar-form-control' - value={this.state.quality} - onChange={(e) => this.update({ quality: e.target.value as VisualQuality })} - > - {qualityOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Sphere detail</span> - <div> - <select - className='molstar-form-control' - value={this.state.detail} - onChange={(e) => this.update({ detail: parseInt(e.target.value) })} - > - {sphereDetailOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color theme</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorTheme.name} - onChange={(e) => { - this.update({ - colorTheme: { - name: e.target.value as ColorThemeName, - value: this.state.colorValue - } - }) - }} - > - {colorThemeOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color value</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorValue} - onChange={(e) => { - const colorValue = Color(parseInt(e.target.value)) - this.update({ - colorTheme: { - name: 'uniform', - value: colorValue - }, - colorValue - }) - }} - > - {colorValueOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.visible} - label='Visibility' - onChange={value => this.update({ visible: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.depthMask} - label='Depth write' - onChange={value => this.update({ depthMask: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.doubleSided} - label='Double sided' - onChange={value => this.update({ doubleSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flipSided} - label='Flip sided' - onChange={value => this.update({ flipSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flatShaded} - label='Flat shaded' - onChange={value => this.update({ flatShaded: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.alpha} - label='Opacity' - min={0} - max={1} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ alpha: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.aspectRatio || 1} - label='Aspect ratio' - min={0.1} - max={10} - step={0.1} - callOnChangeWhileSliding={true} - onChange={value => this.update({ aspectRatio: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.sizeTheme.value || 0.1} - label='Size value' - min={0.01} - max={0.3} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ - sizeTheme: { ...this.state.sizeTheme, value: value } - })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.sizeTheme.factor || 1} - label='Size factor' - min={0.1} - max={3} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ - sizeTheme: { ...this.state.sizeTheme, factor: value } - })} - /> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/distance-restraint.tsx b/src/mol-app/ui/transform/distance-restraint.tsx deleted file mode 100644 index 037532629bf76078090abee3e4600f5cc8698ce2..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/distance-restraint.tsx +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { Toggle } from '../controls/common'; -import { DistanceRestraintEntity } from 'mol-view/state/entity'; -import { DistanceRestraintUpdate } from 'mol-view/state/transform' -import { StateContext } from 'mol-view/state/context'; -import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme/color'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { Color, ColorNames } from 'mol-util/color'; -import { Slider } from '../controls/slider'; -import { Unit } from 'mol-model/structure'; -import { VisualQuality } from 'mol-geo/geometry/geometry'; - -interface DistanceRestraintState { - doubleSided: boolean - flipSided: boolean - flatShaded: boolean - colorTheme: ColorThemeProps - colorValue: Color - sizeTheme: SizeThemeProps - visible: boolean - alpha: number - depthMask: boolean - useFog: boolean - quality: VisualQuality - linkScale: number - linkSpacing: number - linkRadius: number - radialSegments: number - detail: number - unitKinds: Unit.Kind[] -} - -export class DistanceRestraint extends View<Controller<any>, DistanceRestraintState, { transform: DistanceRestraintUpdate, entity: DistanceRestraintEntity, ctx: StateContext }> { - state = { - doubleSided: true, - flipSided: false, - flatShaded: false, - colorTheme: { name: 'element-symbol' } as ColorThemeProps, - colorValue: Color(0x000000), - sizeTheme: { name: 'uniform' } as SizeThemeProps, - visible: true, - alpha: 1, - depthMask: true, - useFog: true, - quality: 'auto' as VisualQuality, - linkScale: 0.4, - linkSpacing: 1, - linkRadius: 0.25, - radialSegments: 16, - detail: 1, - unitKinds: [] as Unit.Kind[] - } - - componentWillMount() { - this.setState({ ...this.state, ...this.props.entity.value.props }) - } - - update(state?: Partial<DistanceRestraintState>) { - const { transform, entity, ctx } = this.props - const newState = { ...this.state, ...state } - this.setState(newState) - transform.apply(ctx, entity, newState) - } - - render() { - const { transform } = this.props - - const qualityOptions = ['auto', 'custom', 'highest', 'high', 'medium', 'low', 'lowest'].map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const colorThemeOptions = ColorThemeNames.map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const colorValueOptions = Object.keys(ColorNames).map((name, idx) => { - return <option key={name} value={(ColorNames as any)[name]}>{name}</option> - }) - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={() => this.update()} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <span>Quality</span> - <div> - <select - className='molstar-form-control' - value={this.state.quality} - onChange={(e) => this.update({ quality: e.target.value as VisualQuality })} - > - {qualityOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color theme</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorTheme.name} - onChange={(e) => { - this.update({ - colorTheme: { - name: e.target.value as ColorThemeName, - value: this.state.colorValue - } - }) - }} - > - {colorThemeOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color value</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorValue} - onChange={(e) => { - const colorValue = Color(parseInt(e.target.value)) - this.update({ - colorTheme: { - name: 'uniform', - value: colorValue - }, - colorValue - }) - }} - > - {colorValueOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.visible} - label='Visibility' - onChange={value => this.update({ visible: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.depthMask} - label='Depth write' - onChange={value => this.update({ depthMask: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.doubleSided} - label='Double sided' - onChange={value => this.update({ doubleSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flipSided} - label='Flip sided' - onChange={value => this.update({ flipSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flatShaded} - label='Flat shaded' - onChange={value => this.update({ flatShaded: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.alpha} - label='Opacity' - min={0} - max={1} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ alpha: value })} - /> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/file-loader.tsx b/src/mol-app/ui/transform/file-loader.tsx deleted file mode 100644 index 32712dfa00a70aebc8f24508bde4a16fde0c470c..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/file-loader.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/** - * 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 { View } from '../view'; -import { FileInput } from '../controls/common'; -import { TransformListController } from '../../controller/transform/list'; -import { FileEntity } from 'mol-view/state/entity'; -import { MmcifFileToModel, ModelToStructure, StructureToBallAndStick, StructureToSpacefill, StructureToDistanceRestraint, StructureToBackbone } from 'mol-view/state/transform'; -import { StateContext } from 'mol-view/state/context'; -import { SpacefillProps } from 'mol-geo/representation/structure/representation/spacefill'; -import { BallAndStickProps } from 'mol-geo/representation/structure/representation/ball-and-stick'; -import { DistanceRestraintProps } from 'mol-geo/representation/structure/representation/distance-restraint'; -import { BackboneProps } from 'mol-geo/representation/structure/representation/backbone'; - -const spacefillProps: Partial<SpacefillProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - quality: 'auto', - useFog: false -} - -const ballAndStickProps: Partial<BallAndStickProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - sizeTheme: { name: 'uniform', value: 0.05 }, - linkRadius: 0.05, - quality: 'auto', - useFog: false -} - -const distanceRestraintProps: Partial<DistanceRestraintProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - linkRadius: 0.5, - quality: 'auto', - useFog: false -} - -const backboneProps: Partial<BackboneProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - quality: 'auto', - useFog: false -} - -export class FileLoader extends View<TransformListController, {}, { ctx: StateContext }> { - render() { - return <div className='molstar-file-loader'> - <FileInput - accept='*.cif' - onChange={async files => { - if (files) { - const ctx = this.props.ctx - const fileEntity = FileEntity.ofFile(ctx, files[0]) - const modelEntity = await MmcifFileToModel.apply(ctx, fileEntity) - const structureEntity = await ModelToStructure.apply(ctx, modelEntity) - - StructureToBallAndStick.apply(ctx, structureEntity, { ...ballAndStickProps, visible: true }) - StructureToSpacefill.apply(ctx, structureEntity, { ...spacefillProps, visible: false }) - StructureToDistanceRestraint.apply(ctx, structureEntity, { ...distanceRestraintProps, visible: false }) - StructureToBackbone.apply(ctx, structureEntity, { ...backboneProps, visible: true }) - } - }} - /> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/list.tsx b/src/mol-app/ui/transform/list.tsx deleted file mode 100644 index f6f72b804a99ac43535e537fa98491f793bbff55..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/list.tsx +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { TransformListController } from '../../controller/transform/list'; -import { AnyTransform } from 'mol-view/state/transform'; -import { Spacefill } from './spacefill'; -import { BallAndStick } from './ball-and-stick'; -import { AnyEntity } from 'mol-view/state/entity'; -import { FileLoader } from './file-loader'; -import { ModelToStructure } from './model'; -import { StructureCenter } from './structure'; -import { Cartoon } from './cartoon'; -import { DistanceRestraint } from './distance-restraint'; -import { Backbone } from './backbone'; -import { UrlLoader } from './url-loader'; -import { Carbohydrate } from './carbohydrate'; - -function getTransformComponent(controller: TransformListController, entity: AnyEntity, transform: AnyTransform) { - switch (transform.kind) { - case 'url-to-spacefill': - return <UrlLoader controller={controller} ctx={controller.context.stage.ctx}></UrlLoader> - case 'file-to-spacefill': - return <FileLoader controller={controller} ctx={controller.context.stage.ctx}></FileLoader> - case 'model-to-structure': - return <ModelToStructure controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></ModelToStructure> - case 'structure-center': - return <StructureCenter controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></StructureCenter> - case 'spacefill-update': - return <Spacefill controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></Spacefill> - case 'ballandstick-update': - return <BallAndStick controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></BallAndStick> - case 'distancerestraint-update': - return <DistanceRestraint controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></DistanceRestraint> - case 'backbone-update': - return <Backbone controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></Backbone> - case 'cartoon-update': - return <Cartoon controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></Cartoon> - case 'carbohydrate-update': - return <Carbohydrate controller={controller} entity={entity} transform={transform} ctx={controller.context.stage.ctx}></Carbohydrate> - } - return <Transform controller={controller} entity={entity} transform={transform}></Transform> -} - -export class Transform extends View<Controller<any>, {}, { transform: AnyTransform, entity: AnyEntity }> { - render() { - const { transform, entity } = this.props - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={(e)=> { - console.log(transform, entity) - }} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - </div> - </div>; - } -} - -export class TransformList extends View<TransformListController, {}, {}> { - render() { - const transforms: JSX.Element[] = [] - const state = this.controller.state.getValue() - if (state && state.entity) { - const entity = state.entity - if (entity) { - state.transforms.forEach(t => { - transforms.push( - <div - key={`${t.inputKind}|${t.outputKind}`} - children={getTransformComponent(this.controller, entity, t)} - /> - ) - }) - } - } - - return <div className='molstar-transform-view' children={transforms} />; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/model.tsx b/src/mol-app/ui/transform/model.tsx deleted file mode 100644 index ebd4d2edb99c7d9e419005c54799d9284aee5bf8..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/model.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { ModelEntity } from 'mol-view/state/entity'; -import { StructureProps, ModelToStructure as ModelToStructureTransform } from 'mol-view/state/transform' -import { StateContext } from 'mol-view/state/context'; - -export class ModelToStructure extends View<Controller<any>, StructureProps, { transform: ModelToStructureTransform, entity: ModelEntity, ctx: StateContext }> { - state = { - assembly: '' - } - - create(state?: Partial<StructureProps>) { - const { transform, entity, ctx } = this.props - console.log('create structure', transform, entity) - const newState = { ...this.state, ...state } - this.setState(newState) - transform.apply(ctx, entity, newState) - } - - render() { - const { transform, entity } = this.props - - const assemblyOptions = entity.value[0].symmetry.assemblies.map((value, idx) => { - return <option key={value.id} value={value.id}>{value.details}</option> - }) - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={() => this.create()} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <span>Details</span> - <div> - <select - className='molstar-form-control' - value={this.state.assembly} - onChange={(e) => this.create({ assembly: e.target.value })} - > - {assemblyOptions} - </select> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/spacefill.tsx b/src/mol-app/ui/transform/spacefill.tsx deleted file mode 100644 index d9694e10eae9c0b7bd3e392112290a40bd1b85a7..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/spacefill.tsx +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { Toggle } from '../controls/common'; -import { SpacefillEntity } from 'mol-view/state/entity'; -import { SpacefillUpdate } from 'mol-view/state/transform' -import { StateContext } from 'mol-view/state/context'; -import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme/color'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { Color, ColorNames } from 'mol-util/color'; -import { Slider } from '../controls/slider'; -import { Unit } from 'mol-model/structure'; -import { VisualQuality } from 'mol-geo/geometry/geometry'; - -interface SpacefillState { - doubleSided: boolean - flipSided: boolean - flatShaded: boolean - detail: number - colorTheme: ColorThemeProps - colorValue: Color - sizeTheme: SizeThemeProps - visible: boolean - alpha: number - depthMask: boolean - useFog: boolean - quality: VisualQuality - unitKinds: Unit.Kind[] -} - -export class Spacefill extends View<Controller<any>, SpacefillState, { transform: SpacefillUpdate, entity: SpacefillEntity, ctx: StateContext }> { - state = { - doubleSided: true, - flipSided: false, - flatShaded: false, - detail: 2, - colorTheme: { name: 'element-symbol' } as ColorThemeProps, - colorValue: Color(0x000000), - sizeTheme: { name: 'uniform', factor: 1 } as SizeThemeProps, - visible: true, - alpha: 1, - depthMask: true, - useFog: true, - quality: 'auto' as VisualQuality, - unitKinds: [] as Unit.Kind[] - } - - componentWillMount() { - this.setState({ ...this.state, ...this.props.entity.value.props }) - } - - update(state?: Partial<SpacefillState>) { - const { transform, entity, ctx } = this.props - const newState = { ...this.state, ...state } - this.setState(newState) - transform.apply(ctx, entity, newState) - } - - render() { - const { transform } = this.props - - const qualityOptions = ['auto', 'custom', 'highest', 'high', 'medium', 'low', 'lowest'].map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const sphereDetailOptions = [0, 1, 2, 3].map((value, idx) => { - return <option key={value} value={value}>{value.toString()}</option> - }) - - const colorThemeOptions = ColorThemeNames.map((name, idx) => { - return <option key={name} value={name}>{name}</option> - }) - - const colorValueOptions = Object.keys(ColorNames).map((name, idx) => { - return <option key={name} value={(ColorNames as any)[name]}>{name}</option> - }) - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={() => this.update()} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <span>Quality</span> - <div> - <select - className='molstar-form-control' - value={this.state.quality} - onChange={(e) => this.update({ quality: e.target.value as VisualQuality })} - > - {qualityOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Sphere detail</span> - <div> - <select - className='molstar-form-control' - value={this.state.detail} - onChange={(e) => this.update({ detail: parseInt(e.target.value) })} - > - {sphereDetailOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color theme</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorTheme.name} - onChange={(e) => { - this.update({ - colorTheme: { - name: e.target.value as ColorThemeName, - value: this.state.colorValue - } - }) - }} - > - {colorThemeOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <span>Color value</span> - <div> - <select - className='molstar-form-control' - value={this.state.colorValue} - onChange={(e) => { - const colorValue = Color(parseInt(e.target.value)) - this.update({ - colorTheme: { - name: 'uniform', - value: colorValue - }, - colorValue - }) - }} - > - {colorValueOptions} - </select> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.visible} - label='Visibility' - onChange={value => this.update({ visible: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.depthMask} - label='Depth write' - onChange={value => this.update({ depthMask: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.doubleSided} - label='Double sided' - onChange={value => this.update({ doubleSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flipSided} - label='Flip sided' - onChange={value => this.update({ flipSided: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Toggle - value={this.state.flatShaded} - label='Flat shaded' - onChange={value => this.update({ flatShaded: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.alpha} - label='Opacity' - min={0} - max={1} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ alpha: value })} - /> - </div> - </div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Slider - value={this.state.sizeTheme.factor || 1} - label='Size factor' - min={0.1} - max={3} - step={0.01} - callOnChangeWhileSliding={true} - onChange={value => this.update({ - sizeTheme: { ...this.state.sizeTheme, factor: value } - })} - /> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/structure.tsx b/src/mol-app/ui/transform/structure.tsx deleted file mode 100644 index 59871cd21908428181550e05f64764959ae70ffd..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/structure.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { View } from '../view'; -import { Controller } from '../../controller/controller'; -import { Button } from '../controls/common'; -import { StructureEntity } from 'mol-view/state/entity'; -import { StructureCenter as StructureCenterTransform } from 'mol-view/state/transform' -import { StateContext } from 'mol-view/state/context'; - -export const ColorThemeInfo = { - 'atom-index': {}, - 'chain-id': {}, - 'element-symbol': {}, - 'instance-index': {}, - 'uniform': {} -} -export type ColorThemeInfo = keyof typeof ColorThemeInfo - -export class StructureCenter extends View<Controller<any>, {}, { transform: StructureCenterTransform, entity: StructureEntity, ctx: StateContext }> { - center() { - const { ctx, entity, transform } = this.props - transform.apply(ctx, entity) - } - - render() { - const { transform } = this.props - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-header'> - <button - className='molstar-btn molstar-btn-link molstar-panel-expander' - onClick={() => {}} - > - <span>[{transform.kind}] {transform.inputKind} -> {transform.outputKind}</span> - </button> - </div> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <div> - <Button onClick={value => this.center()}> - Center - </Button> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/transform/url-loader.tsx b/src/mol-app/ui/transform/url-loader.tsx deleted file mode 100644 index 58667e93d9684bd0e06ec78eef80baf20d6739ea..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/transform/url-loader.tsx +++ /dev/null @@ -1,124 +0,0 @@ -/** - * 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 { View } from '../view'; -import { TransformListController } from '../../controller/transform/list'; -import { UrlEntity } from 'mol-view/state/entity'; -import { ModelToStructure, StructureToBallAndStick, StructureToSpacefill, StructureToDistanceRestraint, StructureToBackbone, MmcifUrlToModel, StructureToCartoon } from 'mol-view/state/transform'; -import { StateContext } from 'mol-view/state/context'; -import { SpacefillProps } from 'mol-geo/representation/structure/representation/spacefill'; -import { BallAndStickProps } from 'mol-geo/representation/structure/representation/ball-and-stick'; -import { DistanceRestraintProps } from 'mol-geo/representation/structure/representation/distance-restraint'; -import { BackboneProps } from 'mol-geo/representation/structure/representation/backbone'; -import { CartoonProps } from 'mol-geo/representation/structure/representation/cartoon'; - -const spacefillProps: Partial<SpacefillProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - quality: 'auto', - useFog: false -} - -const ballAndStickProps: Partial<BallAndStickProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - sizeTheme: { name: 'uniform', value: 0.05 }, - linkRadius: 0.05, - quality: 'auto', - useFog: false -} - -const distanceRestraintProps: Partial<DistanceRestraintProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - linkRadius: 0.5, - quality: 'auto', - useFog: false -} - -const backboneProps: Partial<BackboneProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - quality: 'auto', - useFog: false -} - -const cartoonProps: Partial<CartoonProps> = { - doubleSided: true, - colorTheme: { name: 'chain-id' }, - quality: 'auto', - useFog: false -} - -function getPdbdevUrl(pdbdevId: string) { - return `https://pdb-dev.wwpdb.org/static/cif/${pdbdevId}.cif` -} - -const exampleUrls = { - PDBDEV_00000001: getPdbdevUrl('PDBDEV_00000001'), // ok - PDBDEV_00000002: getPdbdevUrl('PDBDEV_00000002'), // ok - PDBDEV_00000003: getPdbdevUrl('PDBDEV_00000003'), // ok - PDBDEV_00000004: getPdbdevUrl('PDBDEV_00000004'), // TODO issue with cross-link extraction - PDBDEV_00000005: getPdbdevUrl('PDBDEV_00000005'), // ok - PDBDEV_00000006: getPdbdevUrl('PDBDEV_00000006'), // TODO only three spacefill atoms rendered - PDBDEV_00000007: getPdbdevUrl('PDBDEV_00000007'), // TODO only three spacefill atoms rendered - PDBDEV_00000008: getPdbdevUrl('PDBDEV_00000008'), // ok - PDBDEV_00000010: getPdbdevUrl('PDBDEV_00000010'), // ok - PDBDEV_00000011: getPdbdevUrl('PDBDEV_00000011'), // ok - PDBDEV_00000012: getPdbdevUrl('PDBDEV_00000012'), // ok - PDBDEV_00000014: getPdbdevUrl('PDBDEV_00000014'), // ok - PDBDEV_00000016: getPdbdevUrl('PDBDEV_00000016'), -} - -export class UrlLoader extends View<TransformListController, { }, { ctx: StateContext }> { - async load(name: keyof typeof exampleUrls) { - console.log(exampleUrls[name]) - const ctx = this.props.ctx - const urlEntity = UrlEntity.ofUrl(ctx, exampleUrls[name]) - console.log(await urlEntity.value.getData()) - const modelEntity = await MmcifUrlToModel.apply(ctx, urlEntity) - const structureEntity = await ModelToStructure.apply(ctx, modelEntity) - - StructureToBallAndStick.apply(ctx, structureEntity, { ...ballAndStickProps, visible: true }) - StructureToSpacefill.apply(ctx, structureEntity, { ...spacefillProps, visible: false }) - StructureToDistanceRestraint.apply(ctx, structureEntity, { ...distanceRestraintProps, visible: false }) - StructureToBackbone.apply(ctx, structureEntity, { ...backboneProps, visible: true }) - StructureToCartoon.apply(ctx, structureEntity, { ...cartoonProps, visible: false }) - } - - render() { - const exampleOptions = Object.keys(exampleUrls).map(name => { - return <option key={name} value={name}>{name}</option> - }) - - return <div className='molstar-transformer-wrapper'> - <div className='molstar-panel molstar-control molstar-transformer molstar-panel-expanded'> - <div className='molstar-panel-body'> - <div> - <div className='molstar-control-row molstar-options-group'> - <span>Examples</span> - <div> - <select - className='molstar-form-control' - value='' - onChange={(e) => { - if (e.target.value) { - this.load(e.target.value as keyof typeof exampleUrls)} - } - } - > - <option key='' value=''></option> - {exampleOptions} - </select> - </div> - </div> - </div> - </div> - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/view.tsx b/src/mol-app/ui/view.tsx deleted file mode 100644 index d7374759f3ac87084324a13e580bfa666d82d717..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/view.tsx +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - */ - -import * as React from 'react' -import { Observable, Subscription } from 'rxjs'; -import { merge, shallowEqual } from 'mol-util' -import { Context } from '../context/context'; -import { Controller } from '../controller/controller'; - -export abstract class PureView<State, Props, ViewState> extends React.Component<{ - state: State - onChange: (s: State) => void -} & Props, ViewState> { - - protected update(s: State) { - let ns = merge<State>(this.props.state, s); - if (ns !== this.props.state as any) this.props.onChange(ns); - } - - shouldComponentUpdate(nextProps: any, nextState: any) { - return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState); - } -} - -export abstract class ComponentView<Props> extends React.Component<{ context: Context } & Props, {}> { - - // shouldComponentUpdate(nextProps: any, nextState: any) { - // return !shallowEqual(this.props, nextProps); - // } - - private subs: Subscription[] = []; - protected subscribe<T>(stream: Observable<T>, obs: (n: T) => void) { - let sub = stream.subscribe(obs); - this.subs.push(sub); - return sub; - } - - protected unsubscribe(sub: Subscription) { - let idx = this.subs.indexOf(sub); - for (let i = idx; i < this.subs.length - 1; i++) { - this.subs[i] = this.subs[i + 1]; - } - sub.unsubscribe(); - this.subs.pop(); - } - - componentWillUnmount() { - for (let s of this.subs) s.unsubscribe(); - this.subs = []; - } -} - -export abstract class ObserverView<P, S> extends React.Component<P, S> { - private subs: Subscription[] = []; - - protected subscribe<T>(stream: Observable<T>, obs: (n: T) => void) { - let sub = stream.subscribe(obs); - this.subs.push(sub); - return sub; - } - - protected unsubscribe(sub: Subscription) { - let idx = this.subs.indexOf(sub); - for (let i = idx; i < this.subs.length - 1; i++) { - this.subs[i] = this.subs[i + 1]; - } - sub.unsubscribe(); - this.subs.pop(); - } - - componentWillUnmount() { - for (let s of this.subs) s.unsubscribe(); - this.subs = []; - } -} - -export abstract class View<T extends Controller<any>, State, CustomProps> - extends ObserverView<{ controller: T } & CustomProps, State> { - - public get controller(): T { - return this.props.controller as any; - } - - componentWillMount() { - this.subscribe(this.controller.state as any, (s) => { - this.forceUpdate() - }); - } -} \ No newline at end of file diff --git a/src/mol-app/ui/visualization/image-canvas.tsx b/src/mol-app/ui/visualization/image-canvas.tsx deleted file mode 100644 index f70699b2e5cce4f3839112c9bd3c9593724cf541..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/visualization/image-canvas.tsx +++ /dev/null @@ -1,89 +0,0 @@ -/** - * 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' - -type State = { imageData: ImageData, width: number, height: number } - -function getExtend(aspectRatio: number, maxWidth: number, maxHeight: number) { - let width = maxWidth - let height = width / aspectRatio - if (height > maxHeight) { - height = maxHeight - width = height * aspectRatio - } - return { width, height } -} - -export class ImageCanvas extends React.Component<{ imageData: ImageData, aspectRatio: number, maxWidth: number, maxHeight: number }, State> { - private canvas: HTMLCanvasElement | null = null; - private ctx: CanvasRenderingContext2D | null = null; - - state = { - imageData: new ImageData(1, 1), - width: 1, - height: 1 - } - - updateStateFromProps() { - this.setState({ - imageData: this.props.imageData, - ...getExtend(this.props.aspectRatio, this.props.maxWidth, this.props.maxHeight) - }) - } - - updateImage() { - if (this.canvas) { - this.canvas.width = this.state.imageData.width - this.canvas.height = this.state.imageData.height - } - if (this.ctx) { - this.ctx.putImageData(this.state.imageData, 0, 0) - } - } - - componentWillMount() { - this.updateStateFromProps() - } - - componentDidMount() { - if (this.canvas && !this.ctx) { - this.ctx = this.canvas.getContext('2d') - if (this.ctx) this.ctx.imageSmoothingEnabled = false - } - this.updateImage() - } - - componentWillReceiveProps() { - this.updateStateFromProps() - } - - componentDidUpdate() { - this.updateImage() - } - - render() { - return <div - className='molstar-image-canvas' - style={{ - width: this.state.width + 6, - height: this.state.height + 6, - margin: 10, - display: 'inline-block', - border: '3px white solid', - }} - > - <canvas - ref={elm => this.canvas = elm} - style={{ - width: this.state.width, - height: this.state.height, - imageRendering: 'pixelated' - }} - /> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/visualization/sequence-view.tsx b/src/mol-app/ui/visualization/sequence-view.tsx deleted file mode 100644 index 2084dcd6c1305ed52e005af96dc844c33e37b819..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/visualization/sequence-view.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author David Sehnal <david.sehnal@gmail.com> - */ - -import * as React from 'react' -import { View } from '../view'; -import { SequenceViewController } from '../../controller/visualization/sequence-view'; -import { Structure, StructureSequence, Queries, StructureSelection, StructureProperties, StructureQuery } from 'mol-model/structure'; -import { Context } from '../../context/context'; -import { InteractivityEvents } from '../../event/basic'; -import { EmptyLoci } from 'mol-model/loci'; - -export class SequenceView extends View<SequenceViewController, {}, {}> { - render() { - const s = this.controller.latestState.structure; - if (!s) return <div className='molstar-sequence-view-wrap'>No structure available.</div>; - - const seqs = s.models[0].sequence.sequences; - return <div className='molstar-sequence-view-wrap'> - {seqs.map((seq, i) => <EntitySequence key={i} ctx={this.controller.context} seq={seq} structure={s} /> )} - </div>; - } -} - -function createQuery(entityId: string, label_seq_id: number) { - return Queries.generators.atoms({ - entityTest: ctx => StructureProperties.entity.id(ctx.element) === entityId, - residueTest: ctx => StructureProperties.residue.label_seq_id(ctx.element) === label_seq_id - }); -} - -// TODO: this is really ineffective and should be done using a canvas. -class EntitySequence extends React.Component<{ ctx: Context, seq: StructureSequence.Entity, structure: Structure }> { - - raiseInteractityEvent(seqId?: number) { - if (typeof seqId === 'undefined') { - InteractivityEvents.HighlightLoci.dispatch(this.props.ctx, EmptyLoci); - return; - } - - const query = createQuery(this.props.seq.entityId, seqId); - const loci = StructureSelection.toLoci(StructureQuery.run(query, this.props.structure)); - if (loci.elements.length === 0) InteractivityEvents.HighlightLoci.dispatch(this.props.ctx, EmptyLoci); - else InteractivityEvents.HighlightLoci.dispatch(this.props.ctx, loci); - } - - - render() { - const { ctx, seq } = this.props; - const { offset, sequence } = seq.sequence; - - const elems: JSX.Element[] = []; - for (let i = 0, _i = sequence.length; i < _i; i++) { - elems[elems.length] = <ResidueView ctx={ctx} seqId={offset + i} letter={sequence[i]} parent={this} key={i} />; - } - - return <div style={{ wordWrap: 'break-word' }}> - <span style={{ fontWeight: 'bold' }}>{this.props.seq.entityId}:{offset} </span> - {elems} - </div>; - } -} - -class ResidueView extends React.Component<{ ctx: Context, seqId: number, letter: string, parent: EntitySequence }, { isHighlighted: boolean }> { - state = { isHighlighted: false } - - mouseEnter = () => { - this.setState({ isHighlighted: true }); - this.props.parent.raiseInteractityEvent(this.props.seqId); - } - - mouseLeave = () => { - this.setState({ isHighlighted: false }); - this.props.parent.raiseInteractityEvent(); - } - - render() { - return <span onMouseEnter={this.mouseEnter} onMouseLeave={this.mouseLeave} - style={{ cursor: 'pointer', backgroundColor: this.state.isHighlighted ? 'yellow' : void 0 }}> - {this.props.letter} - </span>; - } -} \ No newline at end of file diff --git a/src/mol-app/ui/visualization/viewport.tsx b/src/mol-app/ui/visualization/viewport.tsx deleted file mode 100644 index ed6c563a40673701268de1330556a64680dc23b9..0000000000000000000000000000000000000000 --- a/src/mol-app/ui/visualization/viewport.tsx +++ /dev/null @@ -1,244 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * Adapted from LiteMol - * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' - -import { ViewportController } from '../../controller/visualization/viewport' -import { View } from '../view'; -import { HelpBox, Toggle, Button } from '../controls/common' -import { Slider } from '../controls/slider' -import { ImageCanvas } from './image-canvas'; -import { InteractivityEvents } from '../../event/basic'; -import { labelFirst } from 'mol-view/label'; - -export class ViewportControls extends View<ViewportController, { showSceneOptions?: boolean, showHelp?: boolean }, {}> { - state = { showSceneOptions: false, showHelp: false }; - - private help() { - return <div className='molstar-viewport-controls-scene-options molstar-control'> - <HelpBox title='Rotate' content={<div><div>Left button</div><div>One finger touch</div></div>} /> - <HelpBox title='Zoom' content={<div><div>Right button</div><div>Pinch</div></div>} /> - <HelpBox title='Move' content={<div><div>Middle button</div><div>Two finger touch</div></div>} /> - <HelpBox title='Slab' content={<div><div>Mouse wheel</div><div>Three finger touch</div></div>} /> - </div> - } - - render() { - let state = this.controller.latestState; - - let options: any; - - let layoutController = this.controller.context.layout; - let layoutState = layoutController.latestState; - if (this.state.showSceneOptions) { - options = <div className='molstar-viewport-controls-scene-options molstar-control'> - <Toggle onChange={v => this.controller.setState({ enableFog: v })} value={state.enableFog!} label='Fog' /> - <Slider label='FOV' min={30} max={90} onChange={v => this.controller.setState({ cameraFOV: v }) } value={state.cameraFOV!} /> - <Slider label='Camera Speed' min={1} max={10} step={0.01} onChange={v => this.controller.setState({ cameraSpeed: v }) } value={state.cameraSpeed!} /> - </div>; - } else if (this.state.showHelp) { - options = this.help(); - } - - let controlsShown = !layoutState.hideControls; - return <div className='molstar-viewport-controls' onMouseLeave={() => this.setState({ showSceneOptions: false, showHelp: false })}> - <div className='molstar-viewport-controls-buttons'> - <Button - style='link' - active={this.state.showHelp} - customClass={'molstar-btn-link-toggle-' + (this.state.showHelp ? 'on' : 'off')} - icon='help-circle' - onClick={(e) => this.setState({ showHelp: !this.state.showHelp, showSceneOptions: false }) } title='Controls Help' /> - <Button - style='link' - active={this.state.showSceneOptions} - customClass={'molstar-btn-link-toggle-' + (this.state.showSceneOptions ? 'on' : 'off')} - icon='settings' - onClick={(e) => this.setState({ showSceneOptions: !this.state.showSceneOptions, showHelp: false }) } title='Scene Options' /> - <Button - style='link' - icon='screenshot' - onClick={(e) => this.controller.context.stage.viewer.downloadScreenshot()} - title='Screenshot' /> - <Button onClick={() => { layoutController.update({ hideControls: controlsShown }); this.forceUpdate(); } } - icon='tools' title={controlsShown ? 'Hide Controls' : 'Show Controls'} active={controlsShown } - customClass={'molstar-btn-link-toggle-' + (controlsShown ? 'on' : 'off')} - style='link' /> - <Button onClick={() => layoutController.update({ isExpanded: !layoutState.isExpanded }) } - icon='expand-layout' title={layoutState.isExpanded ? 'Collapse' : 'Expand'} active={layoutState.isExpanded } - customClass={'molstar-btn-link-toggle-' + (layoutState.isExpanded ? 'on' : 'off')} - style='link' /> - <Button - style='link' - icon='reset-scene' - onClick={(e) => this.controller.context.stage.viewer.resetCamera()} - title='Reset camera' /> - </div> - {options} - </div>; - } -} - -export const Logo = () => - <div className='molstar-logo'> - <div> - <div> - <div /> - <div className='molstar-logo-image' /> - </div> - </div> - </div> - - -type ViewportState = { - noWebGl: boolean, - showLogo: boolean, - aspectRatio: number, - width: number - height: number - images: { [k: string]: ImageData } - info: string -} - -export class Viewport extends View<ViewportController, ViewportState, { noWebGl?: boolean, showLogo?: boolean, aspectRatio: number, info: string }> { - private container: HTMLDivElement | null = null; - private canvas: HTMLCanvasElement | null = null; - private defaultBg = { r: 1, g: 1, b: 1 } - state: ViewportState = { - noWebGl: false, - showLogo: true, - images: {}, - aspectRatio: 1, - width: 0, - height: 0, - info: '' - }; - - handleResize() { - if (this.container) { - this.setState({ - aspectRatio: this.container.clientWidth / this.container.clientHeight, - width: this.container.clientWidth, - height: this.container.clientHeight - }) - } - } - - componentDidMount() { - if (!this.canvas || !this.container || !this.controller.context.initStage(this.canvas, this.container)) { - this.setState({ noWebGl: true }); - } - this.handleResize() - - const viewer = this.controller.context.stage.viewer - - viewer.reprCount.subscribe(count => { - this.setState({ - showLogo: false - // showLogo: count === 0 - }) - }) - - viewer.didDraw.subscribe(() => { - // this.setState({ imageData: viewer.getImageData() }) - this.setState({ - images: { - 'object': viewer.getImageData('pickObject'), - 'instance': viewer.getImageData('pickInstance'), - 'group': viewer.getImageData('pickGroup') - } - }) - }) - - viewer.input.resize.subscribe(() => this.handleResize()) - - // TODO: clear highlight on mouse/touch down? - - viewer.input.move.subscribe(({x, y, inside, buttons}) => { - if (!inside || buttons) return - const p = viewer.identify(x, y) - if (p) { - const loci = viewer.getLoci(p) - InteractivityEvents.HighlightLoci.dispatch(this.controller.context, loci); - - // TODO use LabelLoci event and make configurable - const label = labelFirst(loci) - const info = `Object: ${p.objectId}, Instance: ${p.instanceId}, Group: ${p.groupId}, Label: ${label}` - this.setState({ info }) - } - }) - - // TODO filter only for left button/single finger touch? - viewer.input.click.subscribe(({x, y}) => { - const p = viewer.identify(x, y) - if (p) { - const loci = viewer.getLoci(p) - InteractivityEvents.SelectLoci.dispatch(this.controller.context, loci); - } - }) - } - - componentWillUnmount() { - super.componentWillUnmount(); - this.controller.context.destroy(); - } - - renderMissing() { - return <div className='molstar-no-webgl'> - <div> - <p><b>WebGL does not seem to be available.</b></p> - <p>This can be caused by an outdated browser, graphics card driver issue, or bad weather. Sometimes, just restarting the browser helps.</p> - <p>For a list of supported browsers, refer to <a href='http://caniuse.com/#feat=webgl' target='_blank'>http://caniuse.com/#feat=webgl</a>.</p> - </div> - </div> - } - - render() { - if (this.state.noWebGl) return this.renderMissing(); - - const color = this.controller.latestState.clearColor! || this.defaultBg; - return <div className='molstar-viewport' style={{ backgroundColor: `rgb(${255 * color.r}, ${255 * color.g}, ${255 * color.b})` }}> - <div ref={elm => this.container = elm} className='molstar-viewport-container'> - <canvas ref={elm => this.canvas = elm} className='molstar-viewport-canvas'></canvas> - </div> - {this.state.showLogo ? <Logo /> : void 0} - <ViewportControls controller={this.controller} /> - <div - style={{ - position: 'absolute', - top: 10, - left: 10, - padding: 10, - color: 'lightgrey', - background: 'rgba(0, 0, 0, 0.2)' - }} - > - {this.state.info} - </div> - <div - style={{ - position: 'absolute', - bottom: 10, - left: 10, - }} - > - {Object.keys(this.state.images).map(k => { - const imageData = this.state.images[k] - return <ImageCanvas - key={k} - imageData={imageData} - aspectRatio={this.state.aspectRatio} - maxWidth={this.state.width / 4} - maxHeight={this.state.height / 4} - /> - })} - </div> - </div>; - } -} \ No newline at end of file diff --git a/src/mol-geo/geometry/color-data.ts b/src/mol-geo/geometry/color-data.ts index ee1a32c79e19a90e3fb8931df4fe07d51712b75f..7ac3f24cdbd3694240957e0a2a18974006a58d2d 100644 --- a/src/mol-geo/geometry/color-data.ts +++ b/src/mol-geo/geometry/color-data.ts @@ -10,9 +10,10 @@ import { Color } from 'mol-util/color'; import { Vec2, Vec3 } from 'mol-math/linear-algebra'; import { LocationIterator } from '../util/location-iterator'; import { NullLocation } from 'mol-model/location'; -import { LocationColor, ColorThemeProps, ColorTheme } from 'mol-view/theme/color'; +import { LocationColor, ColorThemeProps, ColorTheme, ColorThemeName } from 'mol-view/theme/color'; import { RuntimeContext } from 'mol-task'; import { getGranularity } from './geometry'; +import { Structure } from 'mol-model/structure'; export type ColorType = 'uniform' | 'instance' | 'group' | 'groupInstance' @@ -24,8 +25,27 @@ export type ColorData = { dColorType: ValueCell<string>, } -export function createColors(ctx: RuntimeContext, locationIt: LocationIterator, props: ColorThemeProps, colorData?: ColorData): Promise<ColorData> { - const colorTheme = ColorTheme(props) +export interface ColorProps { + colorTheme: ColorThemeName + colorValue?: Color + structure?: Structure +} + +export function getColorThemeProps(props: ColorProps): ColorThemeProps { + return { + name: props.colorTheme, + // domain: [number, number], + value: props.colorValue, + structure: props.structure, + // color?: LocationColor, + // granularity?: ColorType, + // description?: string, + // legend?: ScaleLegend | TableLegend + } +} + +export function createColors(ctx: RuntimeContext, locationIt: LocationIterator, props: ColorProps, colorData?: ColorData): Promise<ColorData> { + const colorTheme = ColorTheme(getColorThemeProps(props)) switch (getGranularity(locationIt, colorTheme.granularity)) { case 'uniform': return createUniformColor(ctx, locationIt, colorTheme.color, colorData) case 'group': return createGroupColor(ctx, locationIt, colorTheme.color, colorData) diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts index e8b1bfcf602b4e7e56cb980edcf9c77d2e1be9a8..6b5c7253ce0a342f31745056bb1caff41b033466 100644 --- a/src/mol-geo/geometry/geometry.ts +++ b/src/mol-geo/geometry/geometry.ts @@ -15,7 +15,8 @@ import { LocationIterator } from '../util/location-iterator'; import { ColorType } from './color-data'; import { SizeType } from './size-data'; import { Lines } from './lines/lines'; -import { paramDefaultValues, RangeParam, CheckboxParam, SelectParam, ColorParam } from 'mol-view/parameter' +import { paramDefaultValues, RangeParam, BooleanParam, SelectParam, ColorParam, StructureParam } from 'mol-view/parameter' +import { Structure } from 'mol-model/structure'; // @@ -53,12 +54,13 @@ export namespace Geometry { export const Params = { alpha: RangeParam('Opacity', '', 1, 0, 1, 0.01), - visible: CheckboxParam('Visible', '', true), - depthMask: CheckboxParam('Depth Mask', '', true), - useFog: CheckboxParam('Use Fog', '', false), + visible: BooleanParam('Visible', '', true), + depthMask: BooleanParam('Depth Mask', '', true), + useFog: BooleanParam('Use Fog', '', false), quality: SelectParam<VisualQuality>('Quality', '', 'auto', VisualQualityOptions), colorTheme: SelectParam<ColorThemeName>('Color Theme', '', 'uniform', ColorThemeOptions), colorValue: ColorParam('Color Value', '', Color(0xCCCCCC)), + structure: StructureParam('Structure', '', Structure.Empty), } export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps diff --git a/src/mol-geo/geometry/lines/lines.ts b/src/mol-geo/geometry/lines/lines.ts index b3b630de9df2528fbb1dc06bcfbbba8167e9d41c..9e0cba304a392e027395d8b48ba5fc0f4f98f5d7 100644 --- a/src/mol-geo/geometry/lines/lines.ts +++ b/src/mol-geo/geometry/lines/lines.ts @@ -18,7 +18,7 @@ import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { LinesValues } from 'mol-gl/renderable/lines'; import { Mesh } from '../mesh/mesh'; import { LinesBuilder } from './lines-builder'; -import { CheckboxParam, SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; +import { BooleanParam, SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; /** Wide line */ export interface Lines { @@ -93,17 +93,18 @@ export namespace Lines { export const Params = { ...Geometry.Params, - lineSizeAttenuation: CheckboxParam('Line Size Attenuation', '', false), + lineSizeAttenuation: BooleanParam('Line Size Attenuation', '', false), sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), sizeValue: NumberParam('Size Value', '', 1, 0, 0.1, 20), + sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), } export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps export async function createValues(ctx: RuntimeContext, lines: Lines, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<LinesValues> { const { instanceCount, groupCount } = locationIt - const color = await createColors(ctx, locationIt, { name: props.colorTheme, value: props.colorValue }) - const size = await createSizes(ctx, locationIt, { name: props.sizeTheme, value: props.sizeValue }) + const color = await createColors(ctx, locationIt, props) + const size = await createSizes(ctx, locationIt, props) const marker = createMarkers(instanceCount * groupCount) const counts = { drawCount: lines.lineCount * 2 * 3, groupCount, instanceCount } diff --git a/src/mol-geo/geometry/mesh/mesh.ts b/src/mol-geo/geometry/mesh/mesh.ts index b7a8c7c1910c81c833f3f0e6f55286ea9c8a8c49..e87de9bf285eb9bc12a7c581d1ba1e3ebc3a1425 100644 --- a/src/mol-geo/geometry/mesh/mesh.ts +++ b/src/mol-geo/geometry/mesh/mesh.ts @@ -16,7 +16,7 @@ import { TransformData } from '../transform-data'; import { LocationIterator } from '../../util/location-iterator'; import { createColors } from '../color-data'; import { ChunkedArray } from 'mol-data/util'; -import { CheckboxParam, paramDefaultValues } from 'mol-view/parameter'; +import { BooleanParam, paramDefaultValues } from 'mol-view/parameter'; export interface Mesh { readonly kind: 'mesh', @@ -317,16 +317,16 @@ export namespace Mesh { export const Params = { ...Geometry.Params, - doubleSided: CheckboxParam('Double Sided', '', false), - flipSided: CheckboxParam('Flip Sided', '', false), - flatShaded: CheckboxParam('Flat Shaded', '', false), + doubleSided: BooleanParam('Double Sided', '', false), + flipSided: BooleanParam('Flip Sided', '', false), + flatShaded: BooleanParam('Flat Shaded', '', false), } export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps export async function createValues(ctx: RuntimeContext, mesh: Mesh, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<MeshValues> { const { instanceCount, groupCount } = locationIt - const color = await createColors(ctx, locationIt, { name: props.colorTheme, value: props.colorValue }) + const color = await createColors(ctx, locationIt, props) const marker = createMarkers(instanceCount * groupCount) const counts = { drawCount: mesh.triangleCount * 3, groupCount, instanceCount } diff --git a/src/mol-geo/geometry/points/points.ts b/src/mol-geo/geometry/points/points.ts index cd805c2eb3bef9199397d60aac38bf3a13af9ea6..3181353cf9957302fccf4cc00f2bef5a4910065d 100644 --- a/src/mol-geo/geometry/points/points.ts +++ b/src/mol-geo/geometry/points/points.ts @@ -15,8 +15,8 @@ import { createMarkers } from '../marker-data'; import { createSizes } from '../size-data'; import { TransformData } from '../transform-data'; import { LocationIterator } from '../../util/location-iterator'; -import { SizeThemeProps, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; -import { CheckboxParam, NumberParam, SelectParam, paramDefaultValues } from 'mol-view/parameter'; +import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; +import { BooleanParam, NumberParam, SelectParam, paramDefaultValues } from 'mol-view/parameter'; /** Point cloud */ export interface Points { @@ -55,19 +55,20 @@ export namespace Points { export const Params = { ...Geometry.Params, - pointSizeAttenuation: CheckboxParam('Point Size Attenuation', '', false), - pointFilledCircle: CheckboxParam('Point Filled Circle', '', false), - pointEdgeBleach: NumberParam('Point Edge Bleach', '', 0.2, 0, 0.05, 1), + pointSizeAttenuation: BooleanParam('Point Size Attenuation', '', false), + pointFilledCircle: BooleanParam('Point Filled Circle', '', false), + pointEdgeBleach: NumberParam('Point Edge Bleach', '', 0.2, 0, 1, 0.05), sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), - sizeValue: NumberParam('Size Value', '', 1, 0, 0.1, 20), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), } export const DefaultProps = paramDefaultValues(Params) export type Props = typeof DefaultProps export async function createValues(ctx: RuntimeContext, points: Points, transform: TransformData, locationIt: LocationIterator, props: Props): Promise<PointsValues> { const { instanceCount, groupCount } = locationIt - const color = await createColors(ctx, locationIt, { name: props.colorTheme, value: props.colorValue }) - const size = await createSizes(ctx, locationIt, { name: props.sizeTheme, value: props.sizeValue }) + const color = await createColors(ctx, locationIt, props) + const size = await createSizes(ctx, locationIt, props) const marker = createMarkers(instanceCount * groupCount) const counts = { drawCount: points.pointCount, groupCount, instanceCount } diff --git a/src/mol-geo/geometry/size-data.ts b/src/mol-geo/geometry/size-data.ts index 32510ac2024f72a222fc665854291871f9e7197c..c9520dc3d8f3caac128a51013f4e08cd9b5057de 100644 --- a/src/mol-geo/geometry/size-data.ts +++ b/src/mol-geo/geometry/size-data.ts @@ -10,8 +10,9 @@ import { TextureImage, createTextureImage } from 'mol-gl/renderable/util'; import { LocationIterator } from '../util/location-iterator'; import { Location, NullLocation } from 'mol-model/location'; import { RuntimeContext } from 'mol-task'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { SizeThemeProps, SizeTheme, SizeThemeName } from 'mol-view/theme/size'; import { getGranularity } from './geometry'; +import { Structure } from 'mol-model/structure'; export type SizeType = 'uniform' | 'instance' | 'group' | 'groupInstance' @@ -23,8 +24,24 @@ export type SizeData = { dSizeType: ValueCell<string>, } -export async function createSizes(ctx: RuntimeContext, locationIt: LocationIterator, props: SizeThemeProps, sizeData?: SizeData): Promise<SizeData> { - const sizeTheme = SizeTheme(props) +export interface SizeProps { + sizeTheme: SizeThemeName + sizeValue?: number + sizeFactor?: number + structure?: Structure +} + +export function getSizeThemeProps(props: SizeProps): SizeThemeProps { + return { + name: props.sizeTheme, + value: props.sizeValue, + factor: props.sizeFactor, + structure: props.structure, + } +} + +export async function createSizes(ctx: RuntimeContext, locationIt: LocationIterator, props: SizeProps, sizeData?: SizeData): Promise<SizeData> { + const sizeTheme = SizeTheme(getSizeThemeProps(props)) switch (getGranularity(locationIt, sizeTheme.granularity)) { case 'uniform': return createUniformSize(ctx, locationIt, sizeTheme.size, sizeData) case 'group': return createGroupSize(ctx, locationIt, sizeTheme.size, sizeData) diff --git a/src/mol-geo/representation/index.ts b/src/mol-geo/representation/index.ts index 885add00c4940cbc444b5fc30f36c5e1d2e5afc3..0a35e6e892286800372ad3098f52a9612d836cac 100644 --- a/src/mol-geo/representation/index.ts +++ b/src/mol-geo/representation/index.ts @@ -9,11 +9,13 @@ import { RenderObject } from 'mol-gl/render-object' import { PickingId } from '../geometry/picking'; import { Loci } from 'mol-model/loci'; import { MarkerAction } from '../geometry/marker-data'; +import { Params } from 'mol-view/parameter'; export interface RepresentationProps {} export interface Representation<D, P extends RepresentationProps = {}> { readonly label: string + readonly params: Params readonly renderObjects: ReadonlyArray<RenderObject> readonly props: Readonly<P> createOrUpdate: (props?: Partial<P>, data?: D) => Task<void> diff --git a/src/mol-geo/representation/shape/index.ts b/src/mol-geo/representation/shape/index.ts index 6a98661db674e1678e999fbd839c0fa9657e6c4c..6c1f7b1ff79a897a43c5f097b2533712470b5e7a 100644 --- a/src/mol-geo/representation/shape/index.ts +++ b/src/mol-geo/representation/shape/index.ts @@ -11,21 +11,22 @@ import { PickingId } from '../../geometry/picking'; import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci'; import { MarkerAction, applyMarkerAction } from '../../geometry/marker-data'; import { ValueCell } from 'mol-util'; -import { ColorThemeProps } from 'mol-view/theme/color'; +import { ColorThemeName, ColorThemeOptions } from 'mol-view/theme/color'; import { Shape } from 'mol-model/shape'; import { LocationIterator } from '../../util/location-iterator'; import { OrderedSet, Interval } from 'mol-data/int'; import { createIdentityTransform } from '../../geometry/transform-data'; import { createRenderableState } from '../../geometry/geometry'; import { Mesh } from '../../geometry/mesh/mesh'; +import { paramDefaultValues, SelectParam } from 'mol-view/parameter'; export interface ShapeRepresentation<P extends RepresentationProps = {}> extends Representation<Shape, P> { } -export const DefaultShapeProps = { - ...Mesh.DefaultProps, - - colorTheme: { name: 'shape-group' } as ColorThemeProps +export const ShapeParams = { + ...Mesh.Params, + colorTheme: SelectParam<ColorThemeName>('Color Theme', '', 'shape-group', ColorThemeOptions) } +export const DefaultShapeProps = paramDefaultValues(ShapeParams) export type ShapeProps = typeof DefaultShapeProps // TODO @@ -60,6 +61,7 @@ export function ShapeRepresentation<P extends ShapeProps>(): ShapeRepresentation return { label: 'Shape mesh', + params: ShapeParams, get renderObjects () { return renderObjects }, get props () { return currentProps }, createOrUpdate, diff --git a/src/mol-geo/representation/structure/complex-representation.ts b/src/mol-geo/representation/structure/complex-representation.ts index c2fd4ba63c729710fdda88d76d5a8aa677e8b073..cf59bb872b50a527109d3eabeb41cdc8b6bbeda9 100644 --- a/src/mol-geo/representation/structure/complex-representation.ts +++ b/src/mol-geo/representation/structure/complex-representation.ts @@ -10,7 +10,7 @@ import { Task } from 'mol-task' import { PickingId } from '../../geometry/picking'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../../geometry/marker-data'; -import { StructureProps, StructureRepresentation } from '.'; +import { StructureProps, StructureRepresentation, StructureParams } from '.'; import { ComplexVisual } from './complex-visual'; export function ComplexRepresentation<P extends StructureProps>(label: string, visualCtor: () => ComplexVisual<P>): StructureRepresentation<P> { @@ -40,6 +40,7 @@ export function ComplexRepresentation<P extends StructureProps>(label: string, v return { label, + params: StructureParams, // TODO get renderObjects() { return visual && visual.renderObject ? [ visual.renderObject ] : [] }, diff --git a/src/mol-geo/representation/structure/complex-visual.ts b/src/mol-geo/representation/structure/complex-visual.ts index ff65e68974431990ecc06832ef09e9c1dedb2c28..a20063eda17134cbfec34d22f79b4305ce0891f9 100644 --- a/src/mol-geo/representation/structure/complex-visual.ts +++ b/src/mol-geo/representation/structure/complex-visual.ts @@ -11,7 +11,7 @@ import { Mesh } from '../../geometry/mesh/mesh'; import { RuntimeContext } from 'mol-task'; import { LocationIterator } from '../../util/location-iterator'; import { createComplexMeshRenderObject } from './visual/util/common'; -import { StructureProps, DefaultStructureMeshProps, VisualUpdateState } from '.'; +import { StructureProps, VisualUpdateState, StructureMeshParams } from '.'; import { deepEqual, ValueCell } from 'mol-util'; import { PickingId } from '../../geometry/picking'; import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci'; @@ -19,12 +19,16 @@ import { MarkerAction, applyMarkerAction } from '../../geometry/marker-data'; import { Interval } from 'mol-data/int'; import { updateRenderableState } from '../../geometry/geometry'; import { createColors } from '../../geometry/color-data'; +import { UnitKindOptions, UnitKind } from './units-visual'; +import { MultiSelectParam, paramDefaultValues } from 'mol-view/parameter'; export interface ComplexVisual<P extends StructureProps> extends Visual<Structure, P> { } -export const DefaultComplexMeshProps = { - ...DefaultStructureMeshProps +export const ComplexMeshParams = { + ...StructureMeshParams, + unitKinds: MultiSelectParam<UnitKind>('Unit Kind', '', [ 'atomic', 'spheres' ], UnitKindOptions), } +export const DefaultComplexMeshProps = paramDefaultValues(ComplexMeshParams) export type ComplexMeshProps = typeof DefaultComplexMeshProps export interface ComplexMeshVisualBuilder<P extends ComplexMeshProps> { @@ -48,8 +52,7 @@ export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMe let conformationHash: number async function create(ctx: RuntimeContext, structure: Structure, props: Partial<P> = {}) { - currentProps = Object.assign({}, defaultProps, props) - currentProps.colorTheme.structure = structure + currentProps = Object.assign({}, defaultProps, props, { structure }) currentStructure = structure conformationHash = Structure.conformationHash(currentStructure) @@ -61,7 +64,6 @@ export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMe async function update(ctx: RuntimeContext, props: Partial<P>) { const newProps = Object.assign({}, currentProps, props) - newProps.colorTheme.structure = currentStructure if (!renderObject) return false @@ -88,7 +90,7 @@ export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMe } if (updateState.updateColor) { - await createColors(ctx, locationIt, newProps.colorTheme, renderObject.values) + await createColors(ctx, locationIt, newProps, renderObject.values) } // TODO why do I need to cast here? diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-geo/representation/structure/index.ts index b177db9fda68fcac7507d6c8eafaf3dc307d2402..471ca0a035202611b39cab33d6235f64a274d7a2 100644 --- a/src/mol-geo/representation/structure/index.ts +++ b/src/mol-geo/representation/structure/index.ts @@ -6,8 +6,8 @@ */ import { Structure } from 'mol-model/structure'; -import { ColorThemeProps, ColorThemeName, ColorThemeOptions } from 'mol-view/theme/color'; -import { SizeThemeProps, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; +import { ColorThemeName, ColorThemeOptions } from 'mol-view/theme/color'; +import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { Representation, RepresentationProps } from '..'; import { Geometry } from '../../geometry/geometry'; import { Mesh } from '../../geometry/mesh/mesh'; @@ -32,16 +32,18 @@ export const StructureMeshParams = { export const DefaultStructureMeshProps = paramDefaultValues(StructureMeshParams) export type StructureMeshProps = typeof DefaultStructureMeshProps -export const DefaultStructurePointsProps = { - ...Points.DefaultProps, - ...DefaultStructureProps, +export const StructurePointsParams = { + ...Points.Params, + ...StructureParams, } +export const DefaultStructurePointsProps = paramDefaultValues(StructurePointsParams) export type StructurePointsProps = typeof DefaultStructurePointsProps -export const DefaultStructureLinesProps = { - ...Lines.DefaultProps, - ...DefaultStructureProps, +export const StructureLinesParams = { + ...Lines.Params, + ...StructureParams, } +export const DefaultStructureLinesProps = paramDefaultValues(StructureLinesParams) export type StructureLinesProps = typeof DefaultStructureLinesProps export interface VisualUpdateState { diff --git a/src/mol-geo/representation/structure/representation/backbone.ts b/src/mol-geo/representation/structure/representation/backbone.ts index 821876a7ea7d0b4cf2db0770fdf83037605fb3b5..ad6e7e641d94be2794c4b22793a06c5bf0499d49 100644 --- a/src/mol-geo/representation/structure/representation/backbone.ts +++ b/src/mol-geo/representation/structure/representation/backbone.ts @@ -10,12 +10,14 @@ import { Structure } from 'mol-model/structure'; import { Task } from 'mol-task'; import { Loci } from 'mol-model/loci'; import { MarkerAction } from '../../../geometry/marker-data'; -import { PolymerBackboneVisual, DefaultPolymerBackboneProps } from '../visual/polymer-backbone-cylinder'; +import { PolymerBackboneVisual, PolymerBackboneParams } from '../visual/polymer-backbone-cylinder'; import { getQualityProps } from '../../util'; +import { paramDefaultValues } from 'mol-view/parameter'; -export const DefaultBackboneProps = { - ...DefaultPolymerBackboneProps +export const BackboneParams = { + ...PolymerBackboneParams } +export const DefaultBackboneProps = paramDefaultValues(BackboneParams) export type BackboneProps = typeof DefaultBackboneProps export type BackboneRepresentation = StructureRepresentation<BackboneProps> @@ -26,6 +28,7 @@ export function BackboneRepresentation(): BackboneRepresentation { let currentProps: BackboneProps return { label: 'Backbone', + params: BackboneParams, get renderObjects() { return [ ...traceRepr.renderObjects ] }, diff --git a/src/mol-geo/representation/structure/representation/ball-and-stick.ts b/src/mol-geo/representation/structure/representation/ball-and-stick.ts index 93ce4295f349541ce9cf843cbe7719f655af378f..e10c4a0ef73959d91ecad7644547a995648b9b69 100644 --- a/src/mol-geo/representation/structure/representation/ball-and-stick.ts +++ b/src/mol-geo/representation/structure/representation/ball-and-stick.ts @@ -5,24 +5,28 @@ */ import { ComplexRepresentation, StructureRepresentation, UnitsRepresentation } from '..'; -import { ElementSphereVisual, DefaultElementSphereProps } from '../visual/element-sphere'; -import { IntraUnitLinkVisual, DefaultIntraUnitLinkProps } from '../visual/intra-unit-link-cylinder'; +import { ElementSphereVisual, ElementSphereParams } from '../visual/element-sphere'; +import { IntraUnitLinkVisual, IntraUnitLinkParams } from '../visual/intra-unit-link-cylinder'; import { PickingId } from '../../../geometry/picking'; -import { Structure, Unit } from 'mol-model/structure'; +import { Structure } from 'mol-model/structure'; import { Task } from 'mol-task'; import { Loci, isEmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../../../geometry/marker-data'; import { InterUnitLinkVisual } from '../visual/inter-unit-link-cylinder'; -import { SizeThemeProps } from 'mol-view/theme/size'; +import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { getQualityProps } from '../../util'; +import { paramDefaultValues, SelectParam, NumberParam, MultiSelectParam } from 'mol-view/parameter'; +import { UnitKind, UnitKindOptions } from '../units-visual'; -export const DefaultBallAndStickProps = { - ...DefaultElementSphereProps, - ...DefaultIntraUnitLinkProps, - - sizeTheme: { name: 'uniform', value: 0.2 } as SizeThemeProps, - unitKinds: [ Unit.Kind.Atomic ] as Unit.Kind[] +export const BallAndStickParams = { + ...ElementSphereParams, + ...IntraUnitLinkParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 0.1, 20), + sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), + unitKinds: MultiSelectParam<UnitKind>('Unit Kind', '', ['atomic'], UnitKindOptions), } +export const DefaultBallAndStickProps = paramDefaultValues(BallAndStickParams) export type BallAndStickProps = typeof DefaultBallAndStickProps export type BallAndStickRepresentation = StructureRepresentation<BallAndStickProps> @@ -35,6 +39,7 @@ export function BallAndStickRepresentation(): BallAndStickRepresentation { let currentProps: BallAndStickProps return { label: 'Ball & Stick', + params: BallAndStickParams, get renderObjects() { return [ ...elmementRepr.renderObjects, ...intraLinkRepr.renderObjects, ...interLinkRepr.renderObjects ] }, diff --git a/src/mol-geo/representation/structure/representation/carbohydrate.ts b/src/mol-geo/representation/structure/representation/carbohydrate.ts index af3961d3d5d833afa4971d1c6b1456ac3c2b71a9..89b348ba7ebfa92bd170b9985c985da9c7bb405e 100644 --- a/src/mol-geo/representation/structure/representation/carbohydrate.ts +++ b/src/mol-geo/representation/structure/representation/carbohydrate.ts @@ -10,17 +10,20 @@ import { Structure } from 'mol-model/structure'; import { Task } from 'mol-task'; import { Loci, isEmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../../../geometry/marker-data'; -import { CarbohydrateSymbolVisual, DefaultCarbohydrateSymbolProps } from '../visual/carbohydrate-symbol-mesh'; -import { CarbohydrateLinkVisual, DefaultCarbohydrateLinkProps } from '../visual/carbohydrate-link-cylinder'; -import { SizeThemeProps } from 'mol-view/theme/size'; +import { CarbohydrateSymbolVisual, CarbohydrateSymbolParams } from '../visual/carbohydrate-symbol-mesh'; +import { CarbohydrateLinkVisual, CarbohydrateLinkParams } from '../visual/carbohydrate-link-cylinder'; +import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { getQualityProps } from '../../util'; +import { paramDefaultValues, SelectParam, NumberParam } from 'mol-view/parameter'; -export const DefaultCarbohydrateProps = { - ...DefaultCarbohydrateSymbolProps, - ...DefaultCarbohydrateLinkProps, - - sizeTheme: { name: 'uniform', value: 1, factor: 1 } as SizeThemeProps, +export const CarbohydrateParams = { + ...CarbohydrateSymbolParams, + ...CarbohydrateLinkParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 0.1, 20), + sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), } +export const DefaultCarbohydrateProps = paramDefaultValues(CarbohydrateParams) export type CarbohydrateProps = typeof DefaultCarbohydrateProps export type CarbohydrateRepresentation = StructureRepresentation<CarbohydrateProps> @@ -32,6 +35,7 @@ export function CarbohydrateRepresentation(): CarbohydrateRepresentation { let currentProps: CarbohydrateProps return { label: 'Carbohydrate', + params: CarbohydrateParams, get renderObjects() { return [ ...carbohydrateSymbolRepr.renderObjects, ...carbohydrateLinkRepr.renderObjects ] }, diff --git a/src/mol-geo/representation/structure/representation/cartoon.ts b/src/mol-geo/representation/structure/representation/cartoon.ts index bb52e94ec27ec9ffb4eecec8e80f5b51240a8864..0691430a676146066839082891c4b0334d8b8675 100644 --- a/src/mol-geo/representation/structure/representation/cartoon.ts +++ b/src/mol-geo/representation/structure/representation/cartoon.ts @@ -10,21 +10,23 @@ import { Structure } from 'mol-model/structure'; import { Task } from 'mol-task'; import { Loci, isEmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../../../geometry/marker-data'; -import { PolymerTraceVisual, DefaultPolymerTraceProps } from '../visual/polymer-trace-mesh'; -import { PolymerGapVisual, DefaultPolymerGapProps } from '../visual/polymer-gap-cylinder'; -import { NucleotideBlockVisual, DefaultNucleotideBlockProps } from '../visual/nucleotide-block-mesh'; -import { SizeThemeProps } from 'mol-view/theme/size'; +import { PolymerTraceVisual, PolymerTraceParams } from '../visual/polymer-trace-mesh'; +import { PolymerGapVisual, PolymerGapParams } from '../visual/polymer-gap-cylinder'; +import { NucleotideBlockVisual, NucleotideBlockParams } from '../visual/nucleotide-block-mesh'; +import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { getQualityProps } from '../../util'; +import { paramDefaultValues, SelectParam, NumberParam } from 'mol-view/parameter'; // import { PolymerDirectionVisual, DefaultPolymerDirectionProps } from '../visual/polymer-direction-wedge'; -export const DefaultCartoonProps = { - ...DefaultPolymerTraceProps, - ...DefaultPolymerGapProps, - ...DefaultNucleotideBlockProps, - // ...DefaultPolymerDirectionProps, - - sizeTheme: { name: 'uniform', value: 0.2 } as SizeThemeProps, +export const CartoonParams = { + ...PolymerTraceParams, + ...PolymerGapParams, + ...NucleotideBlockParams, + // ...PolymerDirectionParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 0.6, 0, 0.1, 20), } +export const DefaultCartoonProps = paramDefaultValues(CartoonParams) export type CartoonProps = typeof DefaultCartoonProps export type CartoonRepresentation = StructureRepresentation<CartoonProps> @@ -38,6 +40,7 @@ export function CartoonRepresentation(): CartoonRepresentation { let currentProps: CartoonProps return { label: 'Cartoon', + params: CartoonParams, get renderObjects() { return [ ...traceRepr.renderObjects, ...gapRepr.renderObjects, ...blockRepr.renderObjects // , ...directionRepr.renderObjects diff --git a/src/mol-geo/representation/structure/representation/distance-restraint.ts b/src/mol-geo/representation/structure/representation/distance-restraint.ts index 2d9a411bf9b63e19fa86a132fa1ff25e851a3452..5d460bb59c7b971ca1515950e80991f68436b007 100644 --- a/src/mol-geo/representation/structure/representation/distance-restraint.ts +++ b/src/mol-geo/representation/structure/representation/distance-restraint.ts @@ -10,14 +10,17 @@ import { Structure } from 'mol-model/structure'; import { Task } from 'mol-task'; import { Loci } from 'mol-model/loci'; import { MarkerAction } from '../../../geometry/marker-data'; -import { CrossLinkRestraintVisual, DefaultCrossLinkRestraintProps } from '../visual/cross-link-restraint-cylinder'; -import { SizeThemeProps } from 'mol-view/theme/size'; +import { CrossLinkRestraintVisual, CrossLinkRestraintParams } from '../visual/cross-link-restraint-cylinder'; +import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { getQualityProps } from '../../util'; +import { paramDefaultValues, SelectParam, NumberParam } from 'mol-view/parameter'; -export const DefaultDistanceRestraintProps = { - ...DefaultCrossLinkRestraintProps, - sizeTheme: { name: 'uniform', value: 0.25 } as SizeThemeProps, +export const DistanceRestraintParams = { + ...CrossLinkRestraintParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 0.25, 0, 0.05, 20), } +export const DefaultDistanceRestraintProps = paramDefaultValues(DistanceRestraintParams) export type DistanceRestraintProps = typeof DefaultDistanceRestraintProps export type DistanceRestraintRepresentation = StructureRepresentation<DistanceRestraintProps> @@ -28,6 +31,7 @@ export function DistanceRestraintRepresentation(): DistanceRestraintRepresentati let currentProps: DistanceRestraintProps return { label: 'Distance restraint', + params: DistanceRestraintParams, get renderObjects() { return [ ...crossLinkRepr.renderObjects ] }, diff --git a/src/mol-geo/representation/structure/representation/molecular-surface.ts b/src/mol-geo/representation/structure/representation/molecular-surface.ts new file mode 100644 index 0000000000000000000000000000000000000000..9d3d8361aa6ebb85aec92634fc97294b700fd2fe --- /dev/null +++ b/src/mol-geo/representation/structure/representation/molecular-surface.ts @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { UnitsRepresentation } from '..'; +import { GaussianSurfaceVisual, GaussianSurfaceParams } from '../visual/gaussian-surface-mesh'; +import { StructureRepresentation } from '../units-representation'; +import { Structure } from 'mol-model/structure'; +import { MarkerAction } from '../../../geometry/marker-data'; +import { Loci } from 'mol-model/loci'; +import { PickingId } from '../../../geometry/picking'; +import { Task } from 'mol-task'; +import { GaussianWireframeVisual, GaussianWireframeParams } from '../visual/gaussian-surface-wireframe'; +import { getQualityProps } from '../../util'; +import { paramDefaultValues, MultiSelectParam } from 'mol-view/parameter'; + +const VisualOptions = [['surface', 'Surface'], ['wireframe', 'Wireframe']] as [string, string][] + +export const MolecularSurfaceParams = { + ...GaussianSurfaceParams, + ...GaussianWireframeParams, + + visuals: MultiSelectParam<string>('Visuals', '', ['surface'], VisualOptions) +} +export const DefaultMolecularSurfaceProps = paramDefaultValues(MolecularSurfaceParams) +export type MolecularSurfaceProps = typeof DefaultMolecularSurfaceProps + +export type MolecularSurfaceRepresentation = StructureRepresentation<MolecularSurfaceProps> + +export function MolecularSurfaceRepresentation(): MolecularSurfaceRepresentation { + let currentProps: MolecularSurfaceProps + let currentStructure: Structure + const gaussianSurfaceRepr = UnitsRepresentation('Gaussian surface', GaussianSurfaceVisual) + const gaussianWireframeRepr = UnitsRepresentation('Gaussian wireframe', GaussianWireframeVisual) + return { + label: 'Molecular Surface', + params: MolecularSurfaceParams, + get renderObjects() { + const renderObjects = [] + if (currentProps.visuals.includes('surface')) renderObjects.push(...gaussianSurfaceRepr.renderObjects) + if (currentProps.visuals.includes('wireframe')) renderObjects.push(...gaussianWireframeRepr.renderObjects) + return renderObjects + }, + get props() { + return { ...gaussianSurfaceRepr.props, ...gaussianWireframeRepr.props, visuals: currentProps.visuals } + }, + createOrUpdate: (props: Partial<MolecularSurfaceProps> = {}, structure?: Structure) => { + if (structure) currentStructure = structure + const qualityProps = getQualityProps(Object.assign({}, currentProps, props), currentStructure) + currentProps = Object.assign({}, DefaultMolecularSurfaceProps, currentProps, props, qualityProps) + return Task.create('Creating MolecularSurfaceRepresentation', async ctx => { + if (currentProps.visuals.includes('surface')) await gaussianSurfaceRepr.createOrUpdate(currentProps, currentStructure).runInContext(ctx) + if (currentProps.visuals.includes('wireframe')) await gaussianWireframeRepr.createOrUpdate(currentProps, currentStructure).runInContext(ctx) + }) + }, + getLoci: (pickingId: PickingId) => { + return gaussianSurfaceRepr.getLoci(pickingId) + }, + mark: (loci: Loci, action: MarkerAction) => { + return gaussianSurfaceRepr.mark(loci, action) + }, + destroy() { + gaussianSurfaceRepr.destroy() + gaussianWireframeRepr.destroy() + } + } +} \ No newline at end of file diff --git a/src/mol-geo/representation/structure/representation/point.ts b/src/mol-geo/representation/structure/representation/point.ts index 51153cc35c65eda5f527c816629543b044645db3..09049bf3b4cb7a3abc76f7afa590d42f9aa881ca 100644 --- a/src/mol-geo/representation/structure/representation/point.ts +++ b/src/mol-geo/representation/structure/representation/point.ts @@ -5,16 +5,18 @@ */ import { UnitsRepresentation } from '..'; -import { ElementPointVisual, DefaultElementPointProps } from '../visual/element-point'; +import { ElementPointVisual, ElementPointParams } from '../visual/element-point'; import { StructureRepresentation } from '../units-representation'; import { Structure } from 'mol-model/structure'; import { MarkerAction } from '../../../geometry/marker-data'; import { Loci } from 'mol-model/loci'; import { PickingId } from '../../../geometry/picking'; +import { paramDefaultValues } from 'mol-view/parameter'; -export const DefaultPointProps = { - ...DefaultElementPointProps, +export const PointParams = { + ...ElementPointParams, } +export const DefaultPointProps = paramDefaultValues(PointParams) export type PointProps = typeof DefaultPointProps export type PointRepresentation = StructureRepresentation<PointProps> @@ -24,6 +26,7 @@ export function PointRepresentation(): PointRepresentation { const pointRepr = UnitsRepresentation('Point', ElementPointVisual) return { label: 'Point', + params: PointParams, get renderObjects() { return [ ...pointRepr.renderObjects ] }, diff --git a/src/mol-geo/representation/structure/representation/spacefill.ts b/src/mol-geo/representation/structure/representation/spacefill.ts index 2582bb107479c2114dfd1d62113e8b2ef9c68168..740c240c7fd3b42e082e8ae12a3ea7b58f91b565 100644 --- a/src/mol-geo/representation/structure/representation/spacefill.ts +++ b/src/mol-geo/representation/structure/representation/spacefill.ts @@ -5,17 +5,19 @@ */ import { UnitsRepresentation } from '..'; -import { ElementSphereVisual, DefaultElementSphereProps } from '../visual/element-sphere'; +import { ElementSphereVisual, ElementSphereParams } from '../visual/element-sphere'; import { StructureRepresentation } from '../units-representation'; import { Structure } from 'mol-model/structure'; import { PickingId } from '../../../geometry/picking'; import { MarkerAction } from '../../../geometry/marker-data'; import { Loci } from 'mol-model/loci'; import { getQualityProps } from '../../util'; +import { paramDefaultValues } from 'mol-view/parameter'; -export const DefaultSpacefillProps = { - ...DefaultElementSphereProps +export const SpacefillParams = { + ...ElementSphereParams } +export const DefaultSpacefillProps = paramDefaultValues(SpacefillParams) export type SpacefillProps = typeof DefaultSpacefillProps export type SpacefillRepresentation = StructureRepresentation<SpacefillProps> @@ -25,6 +27,7 @@ export function SpacefillRepresentation(): SpacefillRepresentation { const sphereRepr = UnitsRepresentation('Sphere mesh', ElementSphereVisual) return { label: 'Spacefill', + params: SpacefillParams, get renderObjects() { return [ ...sphereRepr.renderObjects ] }, diff --git a/src/mol-geo/representation/structure/representation/surface.ts b/src/mol-geo/representation/structure/representation/surface.ts deleted file mode 100644 index d397bd3eaeee8f085f66217061542aba11329756..0000000000000000000000000000000000000000 --- a/src/mol-geo/representation/structure/representation/surface.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import { UnitsRepresentation } from '..'; -import { GaussianSurfaceVisual, DefaultGaussianSurfaceProps } from '../visual/gaussian-surface-mesh'; -import { StructureRepresentation } from '../units-representation'; -import { Structure } from 'mol-model/structure'; -import { MarkerAction } from '../../../geometry/marker-data'; -import { Loci } from 'mol-model/loci'; -import { PickingId } from '../../../geometry/picking'; -import { Task } from 'mol-task'; -import { DefaultGaussianWireframeProps, GaussianWireframeVisual } from '../visual/gaussian-surface-wireframe'; -import { getQualityProps } from '../../util'; - -export const DefaultSurfaceProps = { - ...DefaultGaussianSurfaceProps, - ...DefaultGaussianWireframeProps, - - visuals: { surface: true, wireframe: false }, -} -export type SurfaceProps = typeof DefaultSurfaceProps - -export type SurfaceRepresentation = StructureRepresentation<SurfaceProps> - -export function SurfaceRepresentation(): SurfaceRepresentation { - let currentProps: SurfaceProps - let currentStructure: Structure - const gaussianSurfaceRepr = UnitsRepresentation('Gaussian surface', GaussianSurfaceVisual) - const gaussianWireframeRepr = UnitsRepresentation('Gaussian wireframe', GaussianWireframeVisual) - return { - label: 'Surface', - get renderObjects() { - const renderObjects = [] - if (currentProps.visuals.surface) renderObjects.push(...gaussianSurfaceRepr.renderObjects) - if (currentProps.visuals.wireframe) renderObjects.push(...gaussianWireframeRepr.renderObjects) - return renderObjects - }, - get props() { - return { ...gaussianSurfaceRepr.props, ...gaussianWireframeRepr.props, visuals: currentProps.visuals } - }, - createOrUpdate: (props: Partial<SurfaceProps> = {}, structure?: Structure) => { - if (structure) currentStructure = structure - const qualityProps = getQualityProps(Object.assign({}, currentProps, props), currentStructure) - currentProps = Object.assign({}, DefaultSurfaceProps, currentProps, props, qualityProps) - return Task.create('Creating SurfaceRepresentation', async ctx => { - if (currentProps.visuals.surface) await gaussianSurfaceRepr.createOrUpdate(currentProps, currentStructure).runInContext(ctx) - if (currentProps.visuals.wireframe) await gaussianWireframeRepr.createOrUpdate(currentProps, currentStructure).runInContext(ctx) - }) - }, - getLoci: (pickingId: PickingId) => { - return gaussianSurfaceRepr.getLoci(pickingId) - }, - mark: (loci: Loci, action: MarkerAction) => { - return gaussianSurfaceRepr.mark(loci, action) - }, - destroy() { - gaussianSurfaceRepr.destroy() - gaussianWireframeRepr.destroy() - } - } -} \ No newline at end of file diff --git a/src/mol-geo/representation/structure/units-representation.ts b/src/mol-geo/representation/structure/units-representation.ts index f3f7e719978d0a68ac557ca84a0f3a9b2cc9dfb4..c2be322d7d5976c9fa1a3f47a3e8b45736423c90 100644 --- a/src/mol-geo/representation/structure/units-representation.ts +++ b/src/mol-geo/representation/structure/units-representation.ts @@ -12,7 +12,7 @@ import { Representation, RepresentationProps, Visual } from '..'; import { PickingId } from '../../geometry/picking'; import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../../geometry/marker-data'; -import { StructureProps } from '.'; +import { StructureProps, StructureParams } from '.'; import { StructureGroup } from './units-visual'; export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<StructureGroup, P> { } @@ -132,6 +132,7 @@ export function UnitsRepresentation<P extends StructureProps>(label: string, vis return { label, + params: StructureParams, // TODO get renderObjects() { const renderObjects: RenderObject[] = [] visuals.forEach(({ visual }) => { diff --git a/src/mol-geo/representation/structure/units-visual.ts b/src/mol-geo/representation/structure/units-visual.ts index df24f1ae5703964ef5735163dc1617ab1a9b4218..fe2abda3d8cdf74a5a7ca02163ffc0d9b968b6a2 100644 --- a/src/mol-geo/representation/structure/units-visual.ts +++ b/src/mol-geo/representation/structure/units-visual.ts @@ -8,7 +8,7 @@ import { Unit, Structure } from 'mol-model/structure'; import { RepresentationProps, Visual } from '../'; -import { DefaultStructureMeshProps, VisualUpdateState, DefaultStructurePointsProps, DefaultStructureLinesProps, StructureMeshParams } from '.'; +import { VisualUpdateState, StructureMeshParams, StructurePointsParams, StructureLinesParams } from '.'; import { RuntimeContext } from 'mol-task'; import { PickingId } from '../../geometry/picking'; import { LocationIterator } from '../../util/location-iterator'; @@ -86,8 +86,7 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu let currentConformationId: UUID async function create(ctx: RuntimeContext, group: Unit.SymmetryGroup, props: Partial<P> = {}) { - currentProps = Object.assign({}, defaultProps, props) - currentProps.colorTheme.structure = currentStructure + currentProps = Object.assign({}, defaultProps, props, { structure: currentStructure }) currentGroup = group const unit = group.units[0] @@ -105,7 +104,6 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu if (!renderObject) return const newProps = Object.assign({}, currentProps, props) - newProps.colorTheme.structure = currentStructure const unit = currentGroup.units[0] locationIt.reset() @@ -120,8 +118,8 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu if (currentGroup.units.length !== locationIt.instanceCount) updateState.updateTransform = true - if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateState.createGeometry = true - if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) updateState.updateColor = true + if (newProps.sizeTheme !== currentProps.sizeTheme) updateState.createGeometry = true + if (newProps.colorTheme !== currentProps.colorTheme) updateState.updateColor = true if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) updateState.createGeometry = true // @@ -135,7 +133,7 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu } if (updateState.createGeometry) { - mesh = newProps.unitKinds.includes(unit.kind) + mesh = includesUnitKind(newProps.unitKinds, unit) ? await createMesh(ctx, unit, currentStructure, newProps, mesh) : Mesh.createEmpty(mesh) ValueCell.update(renderObject.values.drawCount, mesh.triangleCount * 3) @@ -143,7 +141,7 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu } if (updateState.updateColor) { - await createColors(ctx, locationIt, newProps.colorTheme, renderObject.values) + await createColors(ctx, locationIt, newProps, renderObject.values) } // TODO why do I need to cast here? @@ -209,10 +207,11 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu // points -export const DefaultUnitsPointsProps = { - ...DefaultStructurePointsProps, - unitKinds: [ Unit.Kind.Atomic, Unit.Kind.Spheres ] as Unit.Kind[] +export const UnitsPointsParams = { + ...StructurePointsParams, + unitKinds: MultiSelectParam<UnitKind>('Unit Kind', '', [ 'atomic', 'spheres' ], UnitKindOptions), } +export const DefaultUnitsPointsProps = paramDefaultValues(UnitsPointsParams) export type UnitsPointsProps = typeof DefaultUnitsPointsProps export interface UnitsPointVisualBuilder<P extends UnitsPointsProps> { @@ -237,8 +236,7 @@ export function UnitsPointsVisual<P extends UnitsPointsProps>(builder: UnitsPoin let currentConformationId: UUID async function create(ctx: RuntimeContext, group: Unit.SymmetryGroup, props: Partial<P> = {}) { - currentProps = Object.assign({}, defaultProps, props) - currentProps.colorTheme.structure = currentStructure + currentProps = Object.assign({}, defaultProps, props, { structure: currentStructure }) currentGroup = group const unit = group.units[0] @@ -256,7 +254,6 @@ export function UnitsPointsVisual<P extends UnitsPointsProps>(builder: UnitsPoin if (!renderObject) return const newProps = Object.assign({}, currentProps, props) - newProps.colorTheme.structure = currentStructure const unit = currentGroup.units[0] locationIt.reset() @@ -271,8 +268,8 @@ export function UnitsPointsVisual<P extends UnitsPointsProps>(builder: UnitsPoin if (currentGroup.units.length !== locationIt.instanceCount) updateState.updateTransform = true - if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateState.updateSize = true - if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) updateState.updateColor = true + if (newProps.sizeTheme !== currentProps.sizeTheme) updateState.updateSize = true + if (newProps.colorTheme !== currentProps.colorTheme) updateState.updateColor = true if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) updateState.createGeometry = true // @@ -286,7 +283,7 @@ export function UnitsPointsVisual<P extends UnitsPointsProps>(builder: UnitsPoin } if (updateState.createGeometry) { - points = newProps.unitKinds.includes(unit.kind) + points = includesUnitKind(newProps.unitKinds, unit) ? await createPoints(ctx, unit, currentStructure, newProps, points) : Points.createEmpty(points) ValueCell.update(renderObject.values.drawCount, points.pointCount) @@ -294,11 +291,11 @@ export function UnitsPointsVisual<P extends UnitsPointsProps>(builder: UnitsPoin } if (updateState.updateSize) { - await createSizes(ctx, locationIt, newProps.sizeTheme, renderObject.values) + await createSizes(ctx, locationIt, newProps, renderObject.values) } if (updateState.updateColor) { - await createColors(ctx, locationIt, newProps.colorTheme, renderObject.values) + await createColors(ctx, locationIt, newProps, renderObject.values) } // TODO why do I need to cast here? @@ -364,10 +361,11 @@ export function UnitsPointsVisual<P extends UnitsPointsProps>(builder: UnitsPoin // lines -export const DefaultUnitsLinesProps = { - ...DefaultStructureLinesProps, - unitKinds: [ Unit.Kind.Atomic, Unit.Kind.Spheres ] as Unit.Kind[] +export const UnitsLinesParams = { + ...StructureLinesParams, + unitKinds: MultiSelectParam<UnitKind>('Unit Kind', '', [ 'atomic', 'spheres' ], UnitKindOptions), } +export const DefaultUnitsLinesProps = paramDefaultValues(UnitsLinesParams) export type UnitsLinesProps = typeof DefaultUnitsLinesProps export interface UnitsLinesVisualBuilder<P extends UnitsLinesProps> { @@ -392,8 +390,7 @@ export function UnitsLinesVisual<P extends UnitsLinesProps>(builder: UnitsLinesV let currentConformationId: UUID async function create(ctx: RuntimeContext, group: Unit.SymmetryGroup, props: Partial<P> = {}) { - currentProps = Object.assign({}, defaultProps, props) - currentProps.colorTheme.structure = currentStructure + currentProps = Object.assign({}, defaultProps, props, { structure: currentStructure }) currentGroup = group const unit = group.units[0] @@ -411,7 +408,6 @@ export function UnitsLinesVisual<P extends UnitsLinesProps>(builder: UnitsLinesV if (!renderObject) return const newProps = Object.assign({}, currentProps, props) - newProps.colorTheme.structure = currentStructure const unit = currentGroup.units[0] locationIt.reset() @@ -426,8 +422,8 @@ export function UnitsLinesVisual<P extends UnitsLinesProps>(builder: UnitsLinesV if (currentGroup.units.length !== locationIt.instanceCount) updateState.updateTransform = true - if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateState.updateSize = true - if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) updateState.updateColor = true + if (newProps.sizeTheme !== currentProps.sizeTheme) updateState.updateSize = true + if (newProps.colorTheme !== currentProps.colorTheme) updateState.updateColor = true if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) updateState.createGeometry = true // @@ -441,7 +437,7 @@ export function UnitsLinesVisual<P extends UnitsLinesProps>(builder: UnitsLinesV } if (updateState.createGeometry) { - lines = newProps.unitKinds.includes(unit.kind) + lines = includesUnitKind(newProps.unitKinds, unit) ? await createLines(ctx, unit, currentStructure, newProps, lines) : Lines.createEmpty(lines) ValueCell.update(renderObject.values.drawCount, lines.lineCount * 2 * 3) @@ -449,11 +445,11 @@ export function UnitsLinesVisual<P extends UnitsLinesProps>(builder: UnitsLinesV } if (updateState.updateSize) { - await createSizes(ctx, locationIt, newProps.sizeTheme, renderObject.values) + await createSizes(ctx, locationIt, newProps, renderObject.values) } if (updateState.updateColor) { - await createColors(ctx, locationIt, newProps.colorTheme, renderObject.values) + await createColors(ctx, locationIt, newProps, renderObject.values) } // TODO why do I need to cast here? diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts index 243610f4ecc4a9102ddbd334bc62cf0b2ed4679c..926573e83282b2b8ce2cd7c6875d1112425b57cf 100644 --- a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Unit, Structure, Link, StructureElement } from 'mol-model/structure'; +import { Structure, Link, StructureElement } from 'mol-model/structure'; import { ComplexVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' import { Mesh } from '../../../geometry/mesh/mesh'; @@ -12,13 +12,14 @@ import { PickingId } from '../../../geometry/picking'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { Vec3 } from 'mol-math/linear-algebra'; import { LocationIterator } from '../../../util/location-iterator'; -import { createLinkCylinderMesh, DefaultLinkCylinderProps, LinkCylinderProps } from './util/link'; +import { createLinkCylinderMesh, LinkCylinderProps, LinkCylinderParams } from './util/link'; import { OrderedSet, Interval } from 'mol-data/int'; import { ComplexMeshVisual } from '../complex-visual'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { LinkType } from 'mol-model/structure/model/types'; import { BitFlags } from 'mol-util'; -import { DefaultUnitsMeshProps } from '../units-visual'; +import { UnitsMeshParams } from '../units-visual'; +import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; // TODO create seperate visual // for (let i = 0, il = carbohydrates.terminalLinks.length; i < il; ++i) { @@ -36,7 +37,7 @@ const radiusFactor = 0.3 async function createCarbohydrateLinkCylinderMesh(ctx: RuntimeContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { const { links, elements } = structure.carbohydrates - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const location = StructureElement.create() const builderProps = { @@ -60,13 +61,14 @@ async function createCarbohydrateLinkCylinderMesh(ctx: RuntimeContext, structure return createLinkCylinderMesh(ctx, builderProps, props, mesh) } -export const DefaultCarbohydrateLinkProps = { - ...DefaultUnitsMeshProps, - ...DefaultLinkCylinderProps, - sizeTheme: { name: 'physical', factor: 1 } as SizeThemeProps, - detail: 0, - unitKinds: [ Unit.Kind.Atomic, Unit.Kind.Spheres ] as Unit.Kind[] +export const CarbohydrateLinkParams = { + ...UnitsMeshParams, + ...LinkCylinderParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + detail: NumberParam('Sphere Detail', '', 0, 0, 3, 1), } +export const DefaultCarbohydrateLinkProps = paramDefaultValues(CarbohydrateLinkParams) export type CarbohydrateLinkProps = typeof DefaultCarbohydrateLinkProps export function CarbohydrateLinkVisual(): ComplexVisual<CarbohydrateLinkProps> { diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts index b184d219b051a43c629f6daebaf8d94ff9f0d603..70c535d04b46834f49dfe7c70cc198efe36c855c 100644 --- a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts +++ b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Unit, Structure, StructureElement } from 'mol-model/structure'; +import { Structure, StructureElement } from 'mol-model/structure'; import { ComplexVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' import { Mesh } from '../../../geometry/mesh/mesh'; @@ -15,14 +15,15 @@ import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { getSaccharideShape, SaccharideShapes } from 'mol-model/structure/structure/carbohydrates/constants'; import { LocationIterator } from '../../../util/location-iterator'; import { OrderedSet, Interval } from 'mol-data/int'; -import { ComplexMeshVisual, DefaultComplexMeshProps } from '../complex-visual'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual'; +import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { addSphere } from '../../../geometry/mesh/builder/sphere'; import { Box, PerforatedBox } from '../../../primitive/box'; import { OctagonalPyramid, PerforatedOctagonalPyramid } from '../../../primitive/pyramid'; import { Star } from '../../../primitive/star'; import { Octahedron, PerforatedOctahedron } from '../../../primitive/octahedron'; import { DiamondPrism, PentagonalPrism, HexagonalPrism } from '../../../primitive/prism'; +import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; const t = Mat4.identity() const sVec = Vec3.zero() @@ -45,7 +46,7 @@ const hexagonalPrism = HexagonalPrism() async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Structure, props: CarbohydrateSymbolProps, mesh?: Mesh) { const builder = MeshBuilder.create(256, 128, mesh) - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const { detail } = props const carbohydrates = structure.carbohydrates @@ -144,12 +145,13 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru return builder.getMesh() } -export const DefaultCarbohydrateSymbolProps = { - ...DefaultComplexMeshProps, - sizeTheme: { name: 'uniform', value: 1, factor: 1 } as SizeThemeProps, - detail: 0, - unitKinds: [ Unit.Kind.Atomic, Unit.Kind.Spheres ] as Unit.Kind[] +export const CarbohydrateSymbolParams = { + ...ComplexMeshParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + detail: NumberParam('Sphere Detail', '', 0, 0, 3, 1), } +export const DefaultCarbohydrateSymbolProps = paramDefaultValues(CarbohydrateSymbolParams) export type CarbohydrateSymbolProps = typeof DefaultCarbohydrateSymbolProps export function CarbohydrateSymbolVisual(): ComplexVisual<CarbohydrateSymbolProps> { diff --git a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts index 1de9ac740281ec2934bef38579fa7fc124411adf..9b3070e05edd5de1302545dab388b455eff27b76 100644 --- a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts @@ -7,24 +7,25 @@ import { Link, Structure, StructureElement } from 'mol-model/structure'; import { ComplexVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { LinkCylinderProps, DefaultLinkCylinderProps, createLinkCylinderMesh } from './util/link'; +import { LinkCylinderProps, createLinkCylinderMesh, LinkCylinderParams } from './util/link'; import { Mesh } from '../../../geometry/mesh/mesh'; import { PickingId } from '../../../geometry/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; -import { ComplexMeshVisual, DefaultComplexMeshProps } from '../complex-visual'; +import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual'; import { LocationIterator } from '../../../util/location-iterator'; import { Interval } from 'mol-data/int'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size'; import { BitFlags } from 'mol-util'; import { LinkType } from 'mol-model/structure/model/types'; +import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; async function createCrossLinkRestraintCylinderMesh(ctx: RuntimeContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { const crossLinks = structure.crossLinkRestraints if (!crossLinks.count) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const location = StructureElement.create() const builderProps = { @@ -49,13 +50,13 @@ async function createCrossLinkRestraintCylinderMesh(ctx: RuntimeContext, structu return createLinkCylinderMesh(ctx, builderProps, props, mesh) } -export const DefaultCrossLinkRestraintProps = { - ...DefaultComplexMeshProps, - ...DefaultLinkCylinderProps, - sizeTheme: { name: 'physical', factor: 0.3 } as SizeThemeProps, - flipSided: false, - flatShaded: false, +export const CrossLinkRestraintParams = { + ...ComplexMeshParams, + ...LinkCylinderParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), } +export const DefaultCrossLinkRestraintProps = paramDefaultValues(CrossLinkRestraintParams) export type CrossLinkRestraintProps = typeof DefaultCrossLinkRestraintProps export function CrossLinkRestraintVisual(): ComplexVisual<CrossLinkRestraintProps> { diff --git a/src/mol-geo/representation/structure/visual/element-point.ts b/src/mol-geo/representation/structure/visual/element-point.ts index ab6f51d8aa94b00a5de9243ed1c23e5c7447e087..4ca4230e06c44be82f8e4905cdf41e92724574df 100644 --- a/src/mol-geo/representation/structure/visual/element-point.ts +++ b/src/mol-geo/representation/structure/visual/element-point.ts @@ -9,17 +9,19 @@ import { RuntimeContext } from 'mol-task' import { UnitsVisual, VisualUpdateState } from '..'; import { getElementLoci, StructureElementIterator, markElement } from './util/element'; import { Vec3 } from 'mol-math/linear-algebra'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { UnitsPointsVisual, DefaultUnitsPointsProps } from '../units-visual'; +import { SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size'; +import { UnitsPointsVisual, UnitsPointsParams } from '../units-visual'; import { Points } from '../../../geometry/points/points'; import { PointsBuilder } from '../../../geometry/points/points-builder'; +import { SelectParam, NumberParam, BooleanParam, paramDefaultValues } from 'mol-view/parameter'; -export const DefaultElementPointProps = { - ...DefaultUnitsPointsProps, - - sizeTheme: { name: 'uniform', value: 0.2 } as SizeThemeProps, - pointSizeAttenuation: true, +export const ElementPointParams = { + ...UnitsPointsParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + pointSizeAttenuation: BooleanParam('Point Size Attenuation', '', true), } +export const DefaultElementPointProps = paramDefaultValues(ElementPointParams) export type ElementPointProps = typeof DefaultElementPointProps // TODO size diff --git a/src/mol-geo/representation/structure/visual/element-sphere.ts b/src/mol-geo/representation/structure/visual/element-sphere.ts index 80176be24a5a38d8fe1b7ef4d5b7746348074e4c..979d073da90540b962d4d3a6beb26d3d5b5e2c11 100644 --- a/src/mol-geo/representation/structure/visual/element-sphere.ts +++ b/src/mol-geo/representation/structure/visual/element-sphere.ts @@ -7,15 +7,17 @@ import { UnitsVisual, VisualUpdateState } from '..'; import { createElementSphereMesh, markElement, getElementLoci, StructureElementIterator } from './util/element'; -import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; +import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; +import { NumberParam, paramDefaultValues, SelectParam } from 'mol-view/parameter'; +import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; export const ElementSphereParams = { - UnitsMe -} -export const DefaultElementSphereProps = { - ...DefaultUnitsMeshProps, - detail: 0 + ...UnitsMeshParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + detail: NumberParam('Sphere Detail', '', 0, 0, 3, 1), } +export const DefaultElementSphereProps = paramDefaultValues(ElementSphereParams) export type ElementSphereProps = typeof DefaultElementSphereProps export function ElementSphereVisual(): UnitsVisual<ElementSphereProps> { diff --git a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts b/src/mol-geo/representation/structure/visual/gaussian-density-point.ts index 27689484e79dc816298db88a79096cab8dc084f5..a445ac86f65a2e14f85b972eff7c13ba9d05b4c1 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-density-point.ts @@ -10,19 +10,21 @@ import { UnitsVisual, VisualUpdateState } from '..'; import { StructureElementIterator } from './util/element'; import { EmptyLoci } from 'mol-model/loci'; import { Vec3 } from 'mol-math/linear-algebra'; -import { UnitsPointsVisual, DefaultUnitsPointsProps } from '../units-visual'; +import { UnitsPointsVisual, UnitsPointsParams } from '../units-visual'; import { Points } from '../../../geometry/points/points'; import { PointsBuilder } from '../../../geometry/points/points-builder'; -import { SizeThemeProps } from 'mol-view/theme/size'; -import { DefaultGaussianDensityProps, GaussianDensityProps } from 'mol-model/structure/structure/unit/gaussian-density'; +import { SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size'; +import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density'; +import { paramDefaultValues, SelectParam, NumberParam, BooleanParam } from 'mol-view/parameter'; -export const DefaultGaussianDensityPointProps = { - ...DefaultUnitsPointsProps, - ...DefaultGaussianDensityProps, - - sizeTheme: { name: 'uniform', value: 1 } as SizeThemeProps, - pointSizeAttenuation: false, +export const GaussianDensityPointParams = { + ...UnitsPointsParams, + ...GaussianDensityParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + pointSizeAttenuation: BooleanParam('Point Size Attenuation', '', false), } +export const DefaultGaussianDensityPointProps = paramDefaultValues(GaussianDensityPointParams) export type GaussianDensityPointProps = typeof DefaultGaussianDensityPointProps export async function createGaussianDensityPoint(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, points?: Points) { diff --git a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts b/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts index 331ed499a67ff25cda8f2b6c635aed3f98b5972a..510d1b50a0a74e0c458587d1fccae91e291ebf55 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts @@ -8,10 +8,11 @@ import { Unit, Structure } from 'mol-model/structure'; import { UnitsVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' import { Mesh } from '../../../geometry/mesh/mesh'; -import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; +import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; import { StructureElementIterator, getElementLoci, markElement } from './util/element'; import { computeMarchingCubesMesh } from '../../../util/marching-cubes/algorithm'; -import { DefaultGaussianDensityProps, GaussianDensityProps } from 'mol-model/structure/structure/unit/gaussian-density'; +import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density'; +import { paramDefaultValues } from 'mol-view/parameter'; async function createGaussianSurfaceMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> { const { smoothness } = props @@ -31,10 +32,11 @@ async function createGaussianSurfaceMesh(ctx: RuntimeContext, unit: Unit, struct return surface; } -export const DefaultGaussianSurfaceProps = { - ...DefaultUnitsMeshProps, - ...DefaultGaussianDensityProps, +export const GaussianSurfaceParams = { + ...UnitsMeshParams, + ...GaussianDensityParams, } +export const DefaultGaussianSurfaceProps = paramDefaultValues(GaussianSurfaceParams) export type GaussianSurfaceProps = typeof DefaultGaussianSurfaceProps export function GaussianSurfaceVisual(): UnitsVisual<GaussianSurfaceProps> { diff --git a/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts b/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts index 3d2635a3a3a7a690e0e7ce1de732d861eb993fdb..1c5d4e091484a146873d033080dce45fca882d75 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-surface-wireframe.ts @@ -7,11 +7,12 @@ import { Unit, Structure } from 'mol-model/structure'; import { UnitsVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { UnitsLinesVisual, DefaultUnitsLinesProps } from '../units-visual'; +import { UnitsLinesVisual, UnitsLinesParams } from '../units-visual'; import { StructureElementIterator, getElementLoci, markElement } from './util/element'; import { computeMarchingCubesLines } from '../../../util/marching-cubes/algorithm'; import { Lines } from '../../../geometry/lines/lines'; -import { GaussianDensityProps, DefaultGaussianDensityProps } from 'mol-model/structure/structure/unit/gaussian-density'; +import { GaussianDensityProps, GaussianDensityParams } from 'mol-model/structure/structure/unit/gaussian-density'; +import { paramDefaultValues } from 'mol-view/parameter'; async function createGaussianWireframe(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, lines?: Lines): Promise<Lines> { const { smoothness } = props @@ -29,10 +30,11 @@ async function createGaussianWireframe(ctx: RuntimeContext, unit: Unit, structur return wireframe } -export const DefaultGaussianWireframeProps = { - ...DefaultUnitsLinesProps, - ...DefaultGaussianDensityProps, +export const GaussianWireframeParams = { + ...UnitsLinesParams, + ...GaussianDensityParams, } +export const DefaultGaussianWireframeProps = paramDefaultValues(GaussianWireframeParams) export type GaussianWireframeProps = typeof DefaultGaussianWireframeProps export function GaussianWireframeVisual(): UnitsVisual<GaussianWireframeProps> { diff --git a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts b/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts index 0a5ba226e38c1d5fdb3ba1ad9a304a4481a96ef5..c6b9af62db5a28cd6de097a068257704f7067951 100644 --- a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts @@ -7,15 +7,16 @@ import { Link, Structure, StructureElement } from 'mol-model/structure'; import { ComplexVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { LinkCylinderProps, DefaultLinkCylinderProps, createLinkCylinderMesh, LinkIterator } from './util/link'; +import { LinkCylinderProps, createLinkCylinderMesh, LinkIterator, LinkCylinderParams } from './util/link'; import { Mesh } from '../../../geometry/mesh/mesh'; import { PickingId } from '../../../geometry/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; -import { ComplexMeshVisual, DefaultComplexMeshProps } from '../complex-visual'; +import { ComplexMeshVisual, ComplexMeshParams } from '../complex-visual'; import { Interval } from 'mol-data/int'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { BitFlags } from 'mol-util'; +import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; async function createInterUnitLinkCylinderMesh(ctx: RuntimeContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { const links = structure.links @@ -23,7 +24,7 @@ async function createInterUnitLinkCylinderMesh(ctx: RuntimeContext, structure: S if (!bondCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue, factor: props.sizeFactor }) const location = StructureElement.create() const builderProps = { @@ -48,12 +49,14 @@ async function createInterUnitLinkCylinderMesh(ctx: RuntimeContext, structure: S return createLinkCylinderMesh(ctx, builderProps, props, mesh) } -export const DefaultInterUnitLinkProps = { - ...DefaultComplexMeshProps, - ...DefaultLinkCylinderProps, - - sizeTheme: { name: 'physical', factor: 0.3 } as SizeThemeProps, +export const InterUnitLinkParams = { + ...ComplexMeshParams, + ...LinkCylinderParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + sizeFactor: NumberParam('Size Factor', '', 0.3, 0, 10, 0.1), } +export const DefaultInterUnitLinkProps = paramDefaultValues(InterUnitLinkParams) export type InterUnitLinkProps = typeof DefaultInterUnitLinkProps export function InterUnitLinkVisual(): ComplexVisual<InterUnitLinkProps> { diff --git a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts b/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts index df2185a28b9f1505d1fcdf2bf431e36df526308c..26f4f849d4b8ea86e47f10af4efd1219722a8835 100644 --- a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts @@ -8,20 +8,21 @@ import { Unit, Link, StructureElement, Structure } from 'mol-model/structure'; import { UnitsVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { DefaultLinkCylinderProps, LinkCylinderProps, createLinkCylinderMesh, LinkIterator } from './util/link'; +import { LinkCylinderProps, createLinkCylinderMesh, LinkIterator, LinkCylinderParams } from './util/link'; import { Mesh } from '../../../geometry/mesh/mesh'; import { PickingId } from '../../../geometry/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; -import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; +import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; import { Interval } from 'mol-data/int'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { BitFlags } from 'mol-util'; +import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; async function createIntraUnitLinkCylinderMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue, factor: props.sizeFactor }) const location = StructureElement.create(unit) const elements = unit.elements; @@ -62,12 +63,14 @@ async function createIntraUnitLinkCylinderMesh(ctx: RuntimeContext, unit: Unit, return createLinkCylinderMesh(ctx, builderProps, props, mesh) } -export const DefaultIntraUnitLinkProps = { - ...DefaultUnitsMeshProps, - ...DefaultLinkCylinderProps, - - sizeTheme: { name: 'physical', factor: 0.3 } as SizeThemeProps, +export const IntraUnitLinkParams = { + ...UnitsMeshParams, + ...LinkCylinderParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + sizeFactor: NumberParam('Size Factor', '', 0.3, 0, 10, 0.1), } +export const DefaultIntraUnitLinkProps = paramDefaultValues(IntraUnitLinkParams) export type IntraUnitLinkProps = typeof DefaultIntraUnitLinkProps export function IntraUnitLinkVisual(): UnitsVisual<IntraUnitLinkProps> { diff --git a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts index 48733329c73d40cc64bb6eb23416b73826b69375..f29a9a3e772d6c72d18b76087e3efd9c9a3f31af 100644 --- a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts +++ b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts @@ -13,10 +13,11 @@ import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { Segmentation } from 'mol-data/int'; import { MoleculeType, isNucleic, isPurinBase, isPyrimidineBase } from 'mol-model/structure/model/types'; import { getElementIndexForAtomId, getElementIndexForAtomRole } from 'mol-model/structure/util'; -import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual'; +import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; import { addCylinder } from '../../../geometry/mesh/builder/cylinder'; import { Box } from '../../../primitive/box'; import { NucleotideLocationIterator, markNucleotideElement, getNucleotideElementLoci } from './util/nucleotide'; +import { paramDefaultValues } from 'mol-view/parameter'; const p1 = Vec3.zero() const p2 = Vec3.zero() @@ -110,9 +111,10 @@ async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, struct return builder.getMesh() } -export const DefaultNucleotideBlockProps = { - ...DefaultUnitsMeshProps +export const NucleotideBlockParams = { + ...UnitsMeshParams } +export const DefaultNucleotideBlockProps = paramDefaultValues(NucleotideBlockParams) export type NucleotideBlockProps = typeof DefaultNucleotideBlockProps export function NucleotideBlockVisual(): UnitsVisual<NucleotideBlockProps> { diff --git a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts index db7428205695bdcc41335eb12be0c7123fe235d6..ebb2e97951b69d59c9d02a6ada806dbad5821bb8 100644 --- a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts @@ -12,22 +12,26 @@ import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { PolymerBackboneIterator } from './util/polymer'; import { getElementLoci, markElement, StructureElementIterator } from './util/element'; import { Vec3 } from 'mol-math/linear-algebra'; -import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; +import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size'; import { CylinderProps } from '../../../primitive/cylinder'; import { OrderedSet } from 'mol-data/int'; import { addCylinder } from '../../../geometry/mesh/builder/cylinder'; +import { paramDefaultValues, NumberParam, SelectParam } from 'mol-view/parameter'; -export interface PolymerBackboneCylinderProps { - sizeTheme: SizeThemeProps - radialSegments: number +export const PolymerBackboneCylinderParams = { + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + radialSegments: NumberParam('Radial Segments', '', 16, 3, 56, 1), } +export const DefaultPolymerBackboneCylinderProps = paramDefaultValues(PolymerBackboneCylinderParams) +export type PolymerBackboneCylinderProps = typeof DefaultPolymerBackboneCylinderProps async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: PolymerBackboneCylinderProps, mesh?: Mesh) { const polymerElementCount = unit.polymerElements.length if (!polymerElementCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const { radialSegments } = props const vertexCountEstimate = radialSegments * 2 * polymerElementCount * 2 @@ -63,10 +67,11 @@ async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit return builder.getMesh() } -export const DefaultPolymerBackboneProps = { - ...DefaultUnitsMeshProps, - radialSegments: 16 +export const PolymerBackboneParams = { + ...UnitsMeshParams, + ...PolymerBackboneCylinderParams, } +export const DefaultPolymerBackboneProps = paramDefaultValues(PolymerBackboneParams) export type PolymerBackboneProps = typeof DefaultPolymerBackboneProps export function PolymerBackboneVisual(): UnitsVisual<PolymerBackboneProps> { diff --git a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts b/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts index 0b6f96f8844ee94c01e37a7ab5efad3df5fbf4f0..99f02d120f74fc912961ffabfa53eb9c62902693 100644 --- a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts +++ b/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts @@ -12,9 +12,10 @@ import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment, PolymerLocationIterator, getPolymerElementLoci, markPolymerElement } from './util/polymer'; import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { SecondaryStructureType, isNucleic } from 'mol-model/structure/model/types'; -import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; +import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { Wedge } from '../../../primitive/wedge'; +import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; const t = Mat4.identity() const sVec = Vec3.zero() @@ -28,15 +29,18 @@ const heightFactor = 6 const wedge = Wedge() -export interface PolymerDirectionWedgeProps { - sizeTheme: SizeThemeProps +export const PolymerDirectionWedgeParams = { + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), } +export const DefaultPolymerDirectionWedgeProps = paramDefaultValues(PolymerDirectionWedgeParams) +export type PolymerDirectionWedgeProps = typeof DefaultPolymerDirectionWedgeProps async function createPolymerDirectionWedgeMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: PolymerDirectionWedgeProps, mesh?: Mesh) { const polymerElementCount = unit.polymerElements.length if (!polymerElementCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const vertexCount = polymerElementCount * 24 const builder = MeshBuilder.create(vertexCount, vertexCount / 10, mesh) @@ -85,9 +89,11 @@ async function createPolymerDirectionWedgeMesh(ctx: RuntimeContext, unit: Unit, return builder.getMesh() } -export const DefaultPolymerDirectionProps = { - ...DefaultUnitsMeshProps +export const PolymerDirectionParams = { + ...UnitsMeshParams, + ...PolymerDirectionWedgeParams } +export const DefaultPolymerDirectionProps = paramDefaultValues(PolymerDirectionParams) export type PolymerDirectionProps = typeof DefaultPolymerDirectionProps export function PolymerDirectionVisual(): UnitsVisual<PolymerDirectionProps> { diff --git a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts index cab4cd3940e72cad0ea9b5394c1c95435b47aad4..b70b281719db2d7fb033e6b01ae0a288ea97059e 100644 --- a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts @@ -11,24 +11,30 @@ import { Mesh } from '../../../geometry/mesh/mesh'; import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { PolymerGapIterator, PolymerGapLocationIterator, markPolymerGapElement, getPolymerGapElementLoci } from './util/polymer'; import { Vec3 } from 'mol-math/linear-algebra'; -import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; +import { SizeTheme, SizeThemeOptions, SizeThemeName } from 'mol-view/theme/size'; import { CylinderProps } from '../../../primitive/cylinder'; import { addSphere } from '../../../geometry/mesh/builder/sphere'; import { addFixedCountDashedCylinder } from '../../../geometry/mesh/builder/cylinder'; +import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; +import { LinkCylinderParams } from './util/link'; const segmentCount = 10 -export interface PolymerGapCylinderProps { - sizeTheme: SizeThemeProps - radialSegments: number +export const PolymerGapCylinderParams = { + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + sizeFactor: NumberParam('Size Factor', '', 0.3, 0, 10, 0.1), + radialSegments: NumberParam('Radial Segments', '', 16, 3, 56, 1), } +export const DefaultPolymerGapCylinderProps = paramDefaultValues(PolymerGapCylinderParams) +export type PolymerGapCylinderProps = typeof DefaultPolymerGapCylinderProps async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: PolymerGapCylinderProps, mesh?: Mesh) { const polymerGapCount = unit.gapElements.length if (!polymerGapCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue, factor: props.sizeValue }) const { radialSegments } = props const vertexCountEstimate = segmentCount * radialSegments * 2 * polymerGapCount * 2 @@ -71,10 +77,21 @@ async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, str return builder.getMesh() } -export const DefaultPolymerGapProps = { - ...DefaultUnitsMeshProps, - radialSegments: 16 +export const InterUnitLinkParams = { + ...UnitsMeshParams, + ...LinkCylinderParams, + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + sizeFactor: NumberParam('Size Factor', '', 0.3, 0, 10, 0.1), } +export const DefaultIntraUnitLinkProps = paramDefaultValues(InterUnitLinkParams) +export type IntraUnitLinkProps = typeof DefaultIntraUnitLinkProps + +export const PolymerGapParams = { + ...UnitsMeshParams, + ...PolymerGapCylinderParams +} +export const DefaultPolymerGapProps = paramDefaultValues(PolymerGapParams) export type PolymerGapProps = typeof DefaultPolymerGapProps export function PolymerGapVisual(): UnitsVisual<PolymerGapProps> { diff --git a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts index 1fe0a7e3718f62a71d5e49ce830a34876f290ee3..a3d6e7b98b0f1a78ad33ee535a22b7af0dba8e7f 100644 --- a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts +++ b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts @@ -11,18 +11,23 @@ import { Mesh } from '../../../geometry/mesh/mesh'; import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment, PolymerLocationIterator, getPolymerElementLoci, markPolymerElement } from './util/polymer'; import { SecondaryStructureType, isNucleic } from 'mol-model/structure/model/types'; -import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; +import { SizeTheme, SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { addSheet } from '../../../geometry/mesh/builder/sheet'; import { addTube } from '../../../geometry/mesh/builder/tube'; - -export interface PolymerTraceMeshProps { - sizeTheme: SizeThemeProps - linearSegments: number - radialSegments: number - aspectRatio: number - arrowFactor: number +import { SelectParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; + +export const PolymerTraceMeshParams = { + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'physical', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + sizeFactor: NumberParam('Size Factor', '', 0.3, 0, 10, 0.1), + linearSegments: NumberParam('Linear Segments', '', 8, 1, 48, 1), + radialSegments: NumberParam('Radial Segments', '', 16, 3, 56, 1), + aspectRatio: NumberParam('Aspect Ratio', '', 5, 0.1, 5, 0.1), + arrowFactor: NumberParam('Arrow Factor', '', 1.5, 0.1, 5, 0.1), } +export const DefaultPolymerTraceMeshProps = paramDefaultValues(PolymerTraceMeshParams) +export type PolymerTraceMeshProps = typeof DefaultPolymerTraceMeshProps // TODO handle polymer ends properly @@ -30,7 +35,7 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, structure const polymerElementCount = unit.polymerElements.length if (!polymerElementCount) return Mesh.createEmpty(mesh) - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue, factor: props.sizeFactor }) const { linearSegments, radialSegments, aspectRatio, arrowFactor } = props const vertexCount = linearSegments * radialSegments * polymerElementCount + (radialSegments + 1) * polymerElementCount * 2 @@ -83,13 +88,11 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, structure return builder.getMesh() } -export const DefaultPolymerTraceProps = { - ...DefaultUnitsMeshProps, - linearSegments: 8, - radialSegments: 12, - aspectRatio: 5, - arrowFactor: 1.5 +export const PolymerTraceParams = { + ...UnitsMeshParams, + ...PolymerTraceMeshParams } +export const DefaultPolymerTraceProps = paramDefaultValues(PolymerTraceParams) export type PolymerTraceProps = typeof DefaultPolymerTraceProps export function PolymerTraceVisual(): UnitsVisual<PolymerTraceProps> { diff --git a/src/mol-geo/representation/structure/visual/util/element.ts b/src/mol-geo/representation/structure/visual/util/element.ts index a2b871fef8d8b69e3e243851168f6c9613324763..76dfc4a5079bc27e2584b332d41c519a9de01336 100644 --- a/src/mol-geo/representation/structure/visual/util/element.ts +++ b/src/mol-geo/representation/structure/visual/util/element.ts @@ -13,12 +13,13 @@ import { MeshBuilder } from '../../../../geometry/mesh/mesh-builder'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { Interval, OrderedSet } from 'mol-data/int'; import { PickingId } from '../../../../geometry/picking'; -import { SizeTheme, SizeThemeProps } from 'mol-view/theme/size'; +import { SizeTheme, SizeThemeName } from 'mol-view/theme/size'; import { LocationIterator } from '../../../../util/location-iterator'; import { addSphere } from '../../../../geometry/mesh/builder/sphere'; export interface ElementSphereMeshProps { - sizeTheme: SizeThemeProps, + sizeTheme: SizeThemeName, + sizeValue: number, detail: number, } @@ -26,7 +27,7 @@ export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, s const { detail } = props const { elements } = unit; - const sizeTheme = SizeTheme(props.sizeTheme) + const sizeTheme = SizeTheme({ name: props.sizeTheme, value: props.sizeValue }) const elementCount = elements.length; const vertexCount = elementCount * sphereVertexCount(detail) const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh) diff --git a/src/mol-geo/representation/structure/visual/util/link.ts b/src/mol-geo/representation/structure/visual/util/link.ts index cd782a7de28583385ea7e89942b0289c9746d1ad..6cdbae8aba636308fa4a0796bc0a94a42c834548 100644 --- a/src/mol-geo/representation/structure/visual/util/link.ts +++ b/src/mol-geo/representation/structure/visual/util/link.ts @@ -9,19 +9,23 @@ import { RuntimeContext } from 'mol-task'; import { Mesh } from '../../../../geometry/mesh/mesh'; import { MeshBuilder } from '../../../../geometry/mesh/mesh-builder'; import { LinkType } from 'mol-model/structure/model/types'; -import { SizeThemeProps } from 'mol-view/theme/size'; +import { SizeThemeName, SizeThemeOptions } from 'mol-view/theme/size'; import { CylinderProps } from '../../../../primitive/cylinder'; import { LocationIterator } from '../../../../util/location-iterator'; import { Unit, StructureElement, Structure, Link } from 'mol-model/structure'; import { addFixedCountDashedCylinder, addCylinder, addDoubleCylinder } from '../../../../geometry/mesh/builder/cylinder'; - -export const DefaultLinkCylinderProps = { - sizeTheme: { name: 'uniform', value: 0.15 } as SizeThemeProps, - linkScale: 0.4, - linkSpacing: 1, - linkRadius: 0.25, - radialSegments: 16 +import { SelectParam, RangeParam, NumberParam, paramDefaultValues } from 'mol-view/parameter'; + +export const LinkCylinderParams = { + sizeTheme: SelectParam<SizeThemeName>('Size Theme', '', 'uniform', SizeThemeOptions), + sizeValue: NumberParam('Size Value', '', 1, 0, 20, 0.1), + sizeFactor: NumberParam('Size Factor', '', 1, 0, 10, 0.1), + linkScale: RangeParam('Link Scale', '', 0.4, 0, 1, 0.1), + linkSpacing: RangeParam('Link Spacing', '', 1, 0, 2, 0.01), + linkRadius: RangeParam('Link Radius', '', 0.25, 0, 10, 0.05), + radialSegments: NumberParam('Radial Segments', '', 16, 3, 56, 1), } +export const DefaultLinkCylinderProps = paramDefaultValues(LinkCylinderParams) export type LinkCylinderProps = typeof DefaultLinkCylinderProps const tmpShiftV12 = Vec3.zero() diff --git a/src/mol-geo/representation/volume/index.ts b/src/mol-geo/representation/volume/index.ts index 8fb7051da75ddd792066ddbd8112a08c5230fbc5..5f22df51d937b41ce3b94cc69802090748500146 100644 --- a/src/mol-geo/representation/volume/index.ts +++ b/src/mol-geo/representation/volume/index.ts @@ -12,14 +12,16 @@ import { PickingId } from '../../geometry/picking'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../../geometry/marker-data'; import { Geometry } from '../../geometry/geometry'; +import { paramDefaultValues } from 'mol-view/parameter'; export interface VolumeVisual<P extends RepresentationProps = {}> extends Visual<VolumeData, P> { } export interface VolumeRepresentation<P extends RepresentationProps = {}> extends Representation<VolumeData, P> { } -export const DefaultVolumeProps = { - ...Geometry.DefaultProps +export const VolumeParams = { + ...Geometry.Params } +export const DefaultVolumeProps = paramDefaultValues(VolumeParams) export type VolumeProps = typeof DefaultVolumeProps export function VolumeRepresentation<P extends VolumeProps>(visualCtor: (volumeData: VolumeData) => VolumeVisual<P>): VolumeRepresentation<P> { @@ -43,6 +45,7 @@ export function VolumeRepresentation<P extends VolumeProps>(visualCtor: (volumeD return { label: 'Volume mesh', + params: VolumeParams, get renderObjects () { return renderObjects }, get props () { return _props }, createOrUpdate, diff --git a/src/mol-geo/representation/volume/surface.ts b/src/mol-geo/representation/volume/isosurface.ts similarity index 78% rename from src/mol-geo/representation/volume/surface.ts rename to src/mol-geo/representation/volume/isosurface.ts index b6c6b1fce28d6954edd483103926678a5d58a0f8..cc472eeaba5514af3ea59384a420a0d6cf8c0697 100644 --- a/src/mol-geo/representation/volume/surface.ts +++ b/src/mol-geo/representation/volume/isosurface.ts @@ -18,6 +18,7 @@ import { LocationIterator } from '../../util/location-iterator'; import { NullLocation } from 'mol-model/location'; import { createIdentityTransform } from '../../geometry/transform-data'; import { createRenderableState } from '../../geometry/geometry'; +import { paramDefaultValues, NumberParam } from 'mol-view/parameter'; export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValue) { return Task.create<Mesh>('Volume Surface', async ctx => { @@ -36,25 +37,26 @@ export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValu }); } -export const DefaultSurfaceProps = { - ...Mesh.DefaultProps, - isoValue: VolumeIsoValue.relative({ min: 0, max: 0, mean: 0, sigma: 0 }, 0), +export const IsosurfaceParams = { + ...Mesh.Params, + isoValue: NumberParam('Iso Value', '', 2, -5, 5, 0.01), } -export type SurfaceProps = typeof DefaultSurfaceProps +export const DefaultIsosurfaceProps = paramDefaultValues(IsosurfaceParams) +export type IsosurfaceProps = typeof DefaultIsosurfaceProps -export default function SurfaceVisual(): VolumeVisual<SurfaceProps> { +export default function IsosurfaceVisual(): VolumeVisual<IsosurfaceProps> { let renderObject: MeshRenderObject - let currentProps = DefaultSurfaceProps + let currentProps = DefaultIsosurfaceProps return { get renderObject () { return renderObject }, - async createOrUpdate(ctx: RuntimeContext, props: Partial<SurfaceProps> = {}, volume?: VolumeData) { - currentProps = { ...DefaultSurfaceProps, ...props } + async createOrUpdate(ctx: RuntimeContext, props: Partial<IsosurfaceProps> = {}, volume?: VolumeData) { + currentProps = { ...DefaultIsosurfaceProps, ...props } console.log('MOINMOIN') if (!volume) return - const mesh = await computeVolumeSurface(volume, currentProps.isoValue).runAsChild(ctx) + const mesh = await computeVolumeSurface(volume, VolumeIsoValue.relative(volume.dataStats, currentProps.isoValue)).runAsChild(ctx) if (!props.flatShaded) { Mesh.computeNormalsImmediate(mesh) } diff --git a/src/mol-model/structure/structure/unit/gaussian-density.ts b/src/mol-model/structure/structure/unit/gaussian-density.ts index 1c9d5b4f10f649a9d92d298e90f22bff627fc5ef..caff5f4c3bc9df06b75a802b80f50f38fbb3ec17 100644 --- a/src/mol-model/structure/structure/unit/gaussian-density.ts +++ b/src/mol-model/structure/structure/unit/gaussian-density.ts @@ -9,12 +9,14 @@ import { SizeTheme } from 'mol-view/theme/size'; import { GaussianDensity } from 'mol-math/geometry/gaussian-density'; import { Task, RuntimeContext } from 'mol-task'; import { DensityData } from 'mol-math/geometry'; +import { NumberParam, paramDefaultValues } from 'mol-view/parameter'; -export const DefaultGaussianDensityProps = { - resolution: 1, - radiusOffset: 0, - smoothness: 1.5, +export const GaussianDensityParams = { + resolution: NumberParam('Resolution', '', 1, 0.1, 10, 0.1), + radiusOffset: NumberParam('Radius Offset', '', 0, 0, 10, 0.1), + smoothness: NumberParam('Smoothness', '', 1.5, 0, 4, 0.1), } +export const DefaultGaussianDensityProps = paramDefaultValues(GaussianDensityParams) export type GaussianDensityProps = typeof DefaultGaussianDensityProps function getConformation(unit: Unit) { diff --git a/src/mol-view/parameter.ts b/src/mol-view/parameter.ts index 93c95f6490cfe5d9faf205fd279f6d442d74c044..eec8b7a9c08d9503ec60741b16b714a24c752620 100644 --- a/src/mol-view/parameter.ts +++ b/src/mol-view/parameter.ts @@ -5,6 +5,7 @@ */ import { Color } from 'mol-util/color'; +import { Structure } from 'mol-model/structure'; export interface BaseParam<T> { label: string @@ -30,11 +31,11 @@ export function MultiSelectParam<E extends string, T = E[]>(label: string, descr return { type: 'multi-select', label, description, defaultValue, options } } -export interface CheckboxParam extends BaseParam<boolean> { - type: 'checkbox' +export interface BooleanParam extends BaseParam<boolean> { + type: 'boolean' } -export function CheckboxParam(label: string, description: string, defaultValue: boolean): CheckboxParam { - return { type: 'checkbox', label, description, defaultValue } +export function BooleanParam(label: string, description: string, defaultValue: boolean): BooleanParam { + return { type: 'boolean', label, description, defaultValue } } export interface RangeParam extends BaseParam<number> { @@ -73,9 +74,18 @@ export function NumberParam(label: string, description: string, defaultValue: nu return { type: 'number', label, description, defaultValue, min, max, step } } -export type Param = SelectParam<any> | MultiSelectParam<any> | CheckboxParam | RangeParam | TextParam | ColorParam | NumberParam +export interface StructureParam extends BaseParam<Structure> { + type: 'structure' +} +export function StructureParam(label: string, description: string, defaultValue: Structure): StructureParam { + return { type: 'structure', label, description, defaultValue } +} + +export type Param = SelectParam<any> | MultiSelectParam<any> | BooleanParam | RangeParam | TextParam | ColorParam | NumberParam | StructureParam + +export type Params = { [k: string]: Param } -export function paramDefaultValues<T extends { [k: string]: Param }>(params: T) { +export function paramDefaultValues<T extends Params>(params: T) { const d: { [k: string]: any } = {} Object.keys(params).forEach(k => d[k] = params[k].defaultValue) return d as { [k in keyof T]: T[k]['defaultValue'] } diff --git a/src/mol-view/stage.ts b/src/mol-view/stage.ts deleted file mode 100644 index 00e35a60c76ef21b706d0b30fd135fdcc03ce0eb..0000000000000000000000000000000000000000 --- a/src/mol-view/stage.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import Viewer from './viewer' -import { StateContext } from './state/context'; -import { Progress } from 'mol-task'; -import { MmcifUrlToModel, ModelToStructure, StructureToSpacefill, StructureToBallAndStick, StructureToDistanceRestraint, StructureToCartoon, StructureToBackbone, StructureCenter, StructureToCarbohydrate } from './state/transform'; -import { UrlEntity } from './state/entity'; -import { SpacefillProps } from 'mol-geo/representation/structure/representation/spacefill'; -import { Context } from 'mol-app/context/context'; -import { BallAndStickProps } from 'mol-geo/representation/structure/representation/ball-and-stick'; -import { CartoonProps } from 'mol-geo/representation/structure/representation/cartoon'; -import { DistanceRestraintProps } from 'mol-geo/representation/structure/representation/distance-restraint'; -import { BackboneProps } from 'mol-geo/representation/structure/representation/backbone'; -import { CarbohydrateProps } from 'mol-geo/representation/structure/representation/carbohydrate'; -// import { Queries as Q, StructureProperties as SP, Query, Selection } from 'mol-model/structure'; - -const spacefillProps: Partial<SpacefillProps> = { - doubleSided: true, - colorTheme: 'chain-id', - sizeTheme: 'physical', - sizeValue: 1.0, - quality: 'auto', - useFog: false -} - -const ballAndStickProps: Partial<BallAndStickProps> = { - doubleSided: true, - colorTheme: 'chain-id', - sizeTheme: 'uniform', - sizeValue: 0.15, - quality: 'auto', - useFog: false -} - -const distanceRestraintProps: Partial<DistanceRestraintProps> = { - doubleSided: true, - colorTheme: 'cross-link', - sizeTheme: 'uniform', - sizeValue: 0.6, - quality: 'auto', - useFog: false -} - -const backboneProps: Partial<BackboneProps> = { - doubleSided: true, - colorTheme: 'chain-id', - sizeTheme: 'uniform', - sizeValue: 0.3, - quality: 'auto', - useFog: false, - alpha: 0.5 -} - -const cartoonProps: Partial<CartoonProps> = { - doubleSided: true, - colorTheme: 'chain-id', - sizeTheme: 'uniform', - sizeValue: 0.13, - aspectRatio: 8, - quality: 'auto', - useFog: false -} - -const carbohydrateProps: Partial<CarbohydrateProps> = { - doubleSided: true, - colorTheme: 'carbohydrate-symbol', - sizeTheme: 'uniform', - sizeValue: 1, - quality: 'highest', - useFog: false -} - -export class Stage { - viewer: Viewer - ctx = new StateContext(Progress.format) - - constructor(public globalContext: Context) { - - } - - initRenderer (canvas: HTMLCanvasElement, container: HTMLDivElement) { - this.viewer = Viewer.create(canvas, container) - this.viewer.animate() - this.ctx.viewer = this.viewer - - // this.loadPdbid('1jj2') - // this.loadPdbid('1grm') // helix-like sheets - // this.loadPdbid('4umt') // ligand has bond with order 3 - // this.loadPdbid('1crn') // small - // this.loadPdbid('1hrv') // viral assembly - // this.loadPdbid('1rb8') // virus - // this.loadPdbid('1blu') // metal coordination - // this.loadPdbid('3pqr') // inter unit bonds, two polymer chains, ligands, water, carbohydrates linked to protein - // this.loadPdbid('4v5a') // ribosome - // this.loadPdbid('3j3q') // ... - // this.loadPdbid('2np2') // dna - // this.loadPdbid('1d66') // dna - // this.loadPdbid('9dna') // A form dna - // this.loadPdbid('1bna') // B form dna - // this.loadPdbid('199d') // C form dna - // this.loadPdbid('4lb6') // Z form dna - // this.loadPdbid('1egk') // 4-way dna-rna junction - // this.loadPdbid('1y26') // rna - // this.loadPdbid('1xv6') // rna, modified nucleotides - // this.loadPdbid('3bbm') // rna with linker - // this.loadPdbid('1euq') // t-rna - // this.loadPdbid('2e2i') // rna, dna, protein - // this.loadPdbid('1gfl') // GFP, flourophore has carbonyl oxygen removed - // this.loadPdbid('1sfi') // contains cyclic peptid - // this.loadPdbid('3sn6') // discontinuous chains - // this.loadPdbid('2zex') // contains carbohydrate polymer - // this.loadPdbid('3sgj') // contains carbohydrate polymer - // this.loadPdbid('3ina') // contains GlcN and IdoA - // this.loadPdbid('1umz') // contains Xyl (Xyloglucan) - // this.loadPdbid('1mfb') // contains Abe - // this.loadPdbid('2gdu') // contains sucrose - // this.loadPdbid('2fnc') // contains maltotriose - // this.loadPdbid('4zs9') // contains raffinose - // this.loadPdbid('2yft') // contains kestose - // this.loadPdbid('2b5t') // contains large carbohydrate polymer - // this.loadPdbid('1b5f') // contains carbohydrate with alternate locations - // this.loadMmcifUrl(`../../examples/1cbs_full.bcif`) - // this.loadMmcifUrl(`../../examples/1cbs_updated.cif`) - // this.loadMmcifUrl(`../../examples/1crn.cif`) - // this.loadPdbid('5u0q') // mixed dna/rna in same polymer - // this.loadPdbid('1xj9') // PNA (peptide nucleic acid) - // this.loadPdbid('5eme') // PNA (peptide nucleic acid) and RNA - this.loadPdbid('2X3T') // temp - - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000001.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000002.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000003.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000004.cif`) // TODO issue with cross-link extraction, not shown - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000005.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000006.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000007.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000008.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000009.cif`) // TODO sequence related error - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000010.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000011.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000012.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000014.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000015.cif`) // TODO sequence related error - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000016.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000017.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000020.cif`) // ok - // this.loadMmcifUrl(`../../../test/pdb-dev/PDBDEV_00000021.cif`) // ok - } - - async loadMmcifUrl (url: string) { - const urlEntity = UrlEntity.ofUrl(this.ctx, url) - const modelEntity = await MmcifUrlToModel.apply(this.ctx, urlEntity) - const structureEntity = await ModelToStructure.apply(this.ctx, modelEntity) - - StructureToBallAndStick.apply(this.ctx, structureEntity, { ...ballAndStickProps, visible: true }) - StructureToSpacefill.apply(this.ctx, structureEntity, { ...spacefillProps, visible: false }) - StructureToDistanceRestraint.apply(this.ctx, structureEntity, { ...distanceRestraintProps, visible: true }) - StructureToBackbone.apply(this.ctx, structureEntity, { ...backboneProps, visible: false }) - StructureToCartoon.apply(this.ctx, structureEntity, { ...cartoonProps, visible: true }) - StructureToCarbohydrate.apply(this.ctx, structureEntity, { ...carbohydrateProps, visible: true }) - StructureCenter.apply(this.ctx, structureEntity) - - this.globalContext.components.sequenceView.setState({ structure: structureEntity.value }); - - // const structureEntity2 = await ModelToStructure.apply(this.ctx, modelEntity) - // const q1 = Q.generators.atoms({ - // residueTest: l => SP.residue.label_seq_id(l) < 7 - // }); - // structureEntity2.value = Selection.unionStructure(await Query(q1)(structureEntity2.value).run()); - // await StructureToBackbone.apply(this.ctx, structureEntity2, { ...backboneProps, visible: true }) - // await StructureToCartoon.apply(this.ctx, structureEntity2, { ...cartoonProps, visible: true }) - // await StructureToBallAndStick.apply(this.ctx, structureEntity2, { ...ballAndStickProps, visible: false }) - // StructureCenter.apply(this.ctx, structureEntity2) - } - - loadPdbid (pdbid: string) { - // return this.loadMmcifUrl(`http://www.ebi.ac.uk/pdbe/static/entry/${pdbid}_updated.cif`) - return this.loadMmcifUrl(`https://files.rcsb.org/download/${pdbid}.cif`) - } - - dispose () { - // TODO - } -} \ No newline at end of file