mirror of
https://github.com/molstar/molstar.git
synced 2026-06-05 22:31:26 +08:00
Compare commits
31 Commits
v0.7.0-dev
...
v0.7.1-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71bc88c041 | ||
|
|
a5aadfef0e | ||
|
|
0b368ef804 | ||
|
|
f398993d33 | ||
|
|
b6f59ca9c3 | ||
|
|
c857c17bb4 | ||
|
|
3415fe0847 | ||
|
|
1569958a29 | ||
|
|
3543faa0c2 | ||
|
|
251dbf3877 | ||
|
|
32d35efef0 | ||
|
|
8b6428a61d | ||
|
|
dda43370cf | ||
|
|
92c1e979c0 | ||
|
|
ad38a33943 | ||
|
|
88c276a4c7 | ||
|
|
0a3d19235d | ||
|
|
0d90fd1f06 | ||
|
|
02d3274e83 | ||
|
|
2531af2b94 | ||
|
|
850328be4e | ||
|
|
f8ce9cbb65 | ||
|
|
2af9d1cabf | ||
|
|
e8d1737d40 | ||
|
|
0328e93518 | ||
|
|
8a4ab9bdb9 | ||
|
|
410cdb193d | ||
|
|
a278337b4c | ||
|
|
b1308de0b9 | ||
|
|
9705078970 | ||
|
|
b1ca98e945 |
4527
package-lock.json
generated
4527
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
56
package.json
56
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "0.7.0-dev.19",
|
||||
"version": "0.7.1-dev.4",
|
||||
"description": "A comprehensive macromolecular library.",
|
||||
"homepage": "https://github.com/molstar/molstar#readme",
|
||||
"repository": {
|
||||
@@ -34,7 +34,8 @@
|
||||
"model-server-watch": "nodemon --watch lib lib/servers/servers/model/server.js",
|
||||
"volume-server-test": "node lib/servers/servers/volume/server.js --idMap em 'test/${id}.mdb' --defaultPort 1336",
|
||||
"plugin-state": "node lib/servers/servers/plugin-state/index.js",
|
||||
"preversion": "npm run test && npm run build",
|
||||
"preversion": "npm run test",
|
||||
"version": "npm run build",
|
||||
"postversion": "git push && git push --tags"
|
||||
},
|
||||
"files": [
|
||||
@@ -82,68 +83,63 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/add": "^1.13.3",
|
||||
"@graphql-codegen/cli": "^1.13.3",
|
||||
"@graphql-codegen/time": "^1.13.3",
|
||||
"@graphql-codegen/typescript": "^1.13.3",
|
||||
"@graphql-codegen/typescript-graphql-files-modules": "^1.13.3",
|
||||
"@graphql-codegen/typescript-graphql-request": "^1.13.3",
|
||||
"@graphql-codegen/typescript-operations": "^1.13.3",
|
||||
"@graphql-codegen/add": "^1.13.5",
|
||||
"@graphql-codegen/cli": "^1.13.5",
|
||||
"@graphql-codegen/time": "^1.13.5",
|
||||
"@graphql-codegen/typescript": "^1.13.5",
|
||||
"@graphql-codegen/typescript-graphql-files-modules": "^1.13.5",
|
||||
"@graphql-codegen/typescript-graphql-request": "^1.13.5",
|
||||
"@graphql-codegen/typescript-operations": "^1.13.5",
|
||||
"@types/cors": "^2.8.6",
|
||||
"@typescript-eslint/eslint-plugin": "^2.29.0",
|
||||
"@typescript-eslint/parser": "^2.29.0",
|
||||
"@typescript-eslint/eslint-plugin": "^2.32.0",
|
||||
"@typescript-eslint/parser": "^2.32.0",
|
||||
"benchmark": "^2.1.4",
|
||||
"circular-dependency-plugin": "^5.2.0",
|
||||
"concurrently": "^5.1.0",
|
||||
"concurrently": "^5.2.0",
|
||||
"cpx2": "^2.0.0",
|
||||
"css-loader": "^3.5.3",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint": "^7.0.0",
|
||||
"extra-watch-webpack-plugin": "^1.0.3",
|
||||
"file-loader": "^6.0.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"graphql": "^15.0.0",
|
||||
"http-server": "^0.12.1",
|
||||
"jest": "^25.4.0",
|
||||
"jest-raw-loader": "^1.0.1",
|
||||
"http-server": "^0.12.3",
|
||||
"jest": "^26.0.1",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"node-sass": "^4.14.0",
|
||||
"node-sass": "^4.14.1",
|
||||
"raw-loader": "^4.0.1",
|
||||
"resolve-url-loader": "^3.1.1",
|
||||
"sass-loader": "^8.0.2",
|
||||
"simple-git": "^1.132.0",
|
||||
"style-loader": "^1.2.0",
|
||||
"ts-jest": "^25.4.0",
|
||||
"simple-git": "^2.4.0",
|
||||
"style-loader": "^1.2.1",
|
||||
"ts-jest": "^25.5.1",
|
||||
"typescript": "^3.8.3",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-version-file-plugin": "^0.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.9.11",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@types/argparse": "^1.0.38",
|
||||
"@types/benchmark": "^1.0.31",
|
||||
"@types/compression": "1.7.0",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/jest": "^25.2.1",
|
||||
"@types/node": "^13.13.2",
|
||||
"@types/node": "^13.13.5",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"@types/react": "^16.9.34",
|
||||
"@types/react-dom": "^16.9.6",
|
||||
"@types/react": "^16.9.35",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"@types/swagger-ui-dist": "3.0.5",
|
||||
"argparse": "^1.0.10",
|
||||
"body-parser": "^1.19.0",
|
||||
"compression": "^1.7.4",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"immer": "^6.0.3",
|
||||
"immer": "^6.0.5",
|
||||
"immutable": "^3.8.2",
|
||||
"node-fetch": "^2.6.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"rxjs": "^6.5.5",
|
||||
"swagger-ui-dist": "^3.25.0",
|
||||
"tslib": "^1.11.1",
|
||||
"swagger-ui-dist": "^3.25.2",
|
||||
"tslib": "^1.11.2",
|
||||
"util.promisify": "^1.0.1",
|
||||
"xhr2": "^0.2.0"
|
||||
}
|
||||
|
||||
@@ -45,6 +45,9 @@
|
||||
return decodeURIComponent(((window.location.search || '').match(r) || [])[1] || '');
|
||||
}
|
||||
|
||||
var debugMode = getParam('debug-mode', '[^&]+').trim() === '1';
|
||||
if (debugMode) molstar.setDebugMode(debugMode);
|
||||
|
||||
var hideControls = getParam('hide-controls', '[^&]+').trim() === '1';
|
||||
var pdbProvider = getParam('pdb-provider', '[^&]+').trim().toLowerCase();
|
||||
var emdbProvider = getParam('emdb-provider', '[^&]+').trim().toLowerCase();
|
||||
@@ -59,7 +62,7 @@
|
||||
if (snapshotId) viewer.setRemoteSnapshot(snapshotId);
|
||||
|
||||
var snapshotUrl = getParam('snapshot-url', '[^&]+').trim();
|
||||
var snapshotUrlType = getParam('snapshot-url-type', '[^&]+').toLowerCase().trim();
|
||||
var snapshotUrlType = getParam('snapshot-url-type', '[^&]+').toLowerCase().trim() || 'molj';
|
||||
if (snapshotUrl && snapshotUrlType) viewer.loadSnapshotFromUrl(snapshotUrl, snapshotUrlType);
|
||||
|
||||
var structureUrl = getParam('structure-url', '[^&]+').trim();
|
||||
|
||||
@@ -23,8 +23,12 @@ import { ObjectKeys } from '../../mol-util/type-helpers';
|
||||
import { PluginState } from '../../mol-plugin/state';
|
||||
import { DownloadDensity } from '../../mol-plugin-state/actions/volume';
|
||||
import { PluginLayoutControlsDisplay } from '../../mol-plugin/layout';
|
||||
|
||||
require('mol-plugin-ui/skin/light.scss');
|
||||
|
||||
export { PLUGIN_VERSION as version } from '../../mol-plugin/version';
|
||||
export { setProductionMode, setDebugMode } from '../../mol-util/debug';
|
||||
|
||||
const Extensions = {
|
||||
'cellpack': PluginSpec.Behavior(CellPack),
|
||||
'pdbe-structure-quality-report': PluginSpec.Behavior(PDBeStructureQualityReport),
|
||||
|
||||
@@ -69,15 +69,8 @@
|
||||
$('format').value = format;
|
||||
$('format').onchange = function (e) { format = e.target.value; }
|
||||
|
||||
// var url = 'https://www.ebi.ac.uk/pdbe/entry-files/pdb' + pdbId + '.ent';
|
||||
// var format = 'pdb';
|
||||
// var assemblyId = 'deposited';
|
||||
|
||||
BasicMolStarWrapper.init('app' /** or document.getElementById('app') */);
|
||||
BasicMolStarWrapper.setBackground(0xffffff);
|
||||
// BasicMolStarWrapper.load({ url: url, format: format, assemblyId: assemblyId });
|
||||
// BasicMolStarWrapper.toggleSpin();
|
||||
|
||||
|
||||
addControl('Load Asym Unit', () => BasicMolStarWrapper.load({ url: url, format: format }));
|
||||
addControl('Load Assembly', () => BasicMolStarWrapper.load({ url: url, format: format, assemblyId: assemblyId }));
|
||||
|
||||
@@ -56,7 +56,13 @@ class BasicWrapper {
|
||||
const trajectory = await this.plugin.builders.structure.parseTrajectory(data, format);
|
||||
|
||||
await this.plugin.builders.structure.hierarchy.applyPreset(trajectory, 'default', {
|
||||
structure: assemblyId ? { name: 'assembly', params: { id: assemblyId } } : { name: 'deposited', params: { } },
|
||||
structure: assemblyId ? {
|
||||
name: 'assembly',
|
||||
params: { id: assemblyId }
|
||||
} : {
|
||||
name: 'model',
|
||||
params: { }
|
||||
},
|
||||
showUnitcell: false,
|
||||
representationPreset: 'auto'
|
||||
});
|
||||
|
||||
@@ -105,7 +105,7 @@ class LightingDemo {
|
||||
const data = await this.plugin.builders.data.download({ url: Asset.Url(url), isBinary }, { state: { isGhost: true } });
|
||||
const trajectory = await this.plugin.builders.structure.parseTrajectory(data, format);
|
||||
const model = await this.plugin.builders.structure.createModel(trajectory);
|
||||
const structure = await this.plugin.builders.structure.createStructure(model, assemblyId ? { name: 'assembly', params: { id: assemblyId } } : { name: 'deposited', params: { } });
|
||||
const structure = await this.plugin.builders.structure.createStructure(model, assemblyId ? { name: 'assembly', params: { id: assemblyId } } : { name: 'model', params: { } });
|
||||
|
||||
const polymer = await this.plugin.builders.structure.tryCreateComponentStatic(structure, 'polymer');
|
||||
if (polymer) await this.plugin.builders.structure.representation.addRepresentation(polymer, { type: 'spacefill', color: 'illustrative' });
|
||||
|
||||
@@ -88,10 +88,6 @@
|
||||
$('isBinary').checked = isBinary;
|
||||
$('isBinary').onchange = function (e) { isBinary = !!e.target.checked; };
|
||||
|
||||
// var url = 'https://www.ebi.ac.uk/pdbe/entry-files/pdb' + pdbId + '.ent';
|
||||
// var format = 'pdb';
|
||||
// var assemblyId = 'deposited';
|
||||
|
||||
function loadAndSnapshot(params) {
|
||||
PluginWrapper.load(params).then(() => {
|
||||
setTimeout(() => snapshot = PluginWrapper.plugin.state.getSnapshot({ canvas3d: false /* do not save spinning state */ }), 500);
|
||||
|
||||
@@ -89,9 +89,12 @@ class MolStarProteopediaWrapper {
|
||||
private structure(assemblyId: string) {
|
||||
const model = this.state.build().to(StateElements.Model);
|
||||
const props = {
|
||||
type: {
|
||||
type: assemblyId ? {
|
||||
name: 'assembly' as const,
|
||||
params: { id: assemblyId || 'deposited' }
|
||||
params: { id: assemblyId }
|
||||
} : {
|
||||
name: 'model' as const,
|
||||
params: { }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -196,7 +199,7 @@ class MolStarProteopediaWrapper {
|
||||
|
||||
private emptyLoadedParams: LoadParams = { url: '', format: 'cif', isBinary: false, assemblyId: '' };
|
||||
private loadedParams: LoadParams = { url: '', format: 'cif', isBinary: false, assemblyId: '' };
|
||||
async load({ url, format = 'cif', assemblyId = 'deposited', isBinary = false, representationStyle }: LoadParams) {
|
||||
async load({ url, format = 'cif', assemblyId = '', isBinary = false, representationStyle }: LoadParams) {
|
||||
let loadType: 'full' | 'update' = 'full';
|
||||
|
||||
const state = this.plugin.state.data;
|
||||
@@ -220,9 +223,12 @@ class MolStarProteopediaWrapper {
|
||||
const info = await this.doInfo(true);
|
||||
const asmId = (assemblyId === 'preferred' && info && info.preferredAssemblyId) || assemblyId;
|
||||
const props = {
|
||||
type: {
|
||||
type: assemblyId ? {
|
||||
name: 'assembly' as const,
|
||||
params: { id: asmId || 'deposited' }
|
||||
params: { id: asmId }
|
||||
} : {
|
||||
name: 'model' as const,
|
||||
params: { }
|
||||
}
|
||||
};
|
||||
tree.to(StateElements.Assembly).update(StateTransforms.Model.StructureFromModel, p => ({ ...p, ...props }));
|
||||
|
||||
@@ -35,7 +35,7 @@ export function isBiologicalAssembly(structure: Structure): boolean {
|
||||
const mmcif = structure.models[0].sourceData.data.db;
|
||||
if (!mmcif.pdbx_struct_assembly.details.isDefined) return false;
|
||||
const id = structure.units[0].conformation.operator.assembly?.id || '';
|
||||
if (id === '' || id === 'deposited') return true;
|
||||
if (id === '') return true;
|
||||
const indices = Column.indicesOf(mmcif.pdbx_struct_assembly.id, e => e === id);
|
||||
if (indices.length !== 1) return false;
|
||||
const details = mmcif.pdbx_struct_assembly.details.value(indices[0]);
|
||||
@@ -63,7 +63,7 @@ export namespace AssemblySymmetry {
|
||||
|
||||
const client = new GraphQLClient(props.serverUrl, ctx.assetManager);
|
||||
const variables: AssemblySymmetryQueryVariables = {
|
||||
assembly_id: structure.units[0].conformation.operator.assembly?.id || 'deposited',
|
||||
assembly_id: structure.units[0].conformation.operator.assembly?.id || '',
|
||||
entry_id: structure.units[0].model.entryId
|
||||
};
|
||||
const result = await client.request(ctx.runtime, query, variables);
|
||||
|
||||
@@ -16,8 +16,7 @@ import { StateAction, StateSelection } from '../../../mol-state';
|
||||
import { PluginStateObject } from '../../../mol-plugin-state/objects';
|
||||
import { PluginContext } from '../../../mol-plugin/context';
|
||||
import { Task } from '../../../mol-task';
|
||||
import Check from '@material-ui/icons/Check';
|
||||
import Extension from '@material-ui/icons/Extension';
|
||||
import { ExtensionSvg, CheckSvg } from '../../../mol-plugin-ui/controls/icons';
|
||||
|
||||
interface AssemblySymmetryControlState extends CollapsableState {
|
||||
isBusy: boolean
|
||||
@@ -30,7 +29,7 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy
|
||||
isCollapsed: false,
|
||||
isBusy: false,
|
||||
isHidden: true,
|
||||
brand: { accent: 'cyan', svg: Extension }
|
||||
brand: { accent: 'cyan', svg: ExtensionSvg }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -62,7 +61,7 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy
|
||||
renderEnable() {
|
||||
const pivot = this.pivot;
|
||||
if (!pivot.cell.parent) return null;
|
||||
return <ApplyActionControl state={pivot.cell.parent} action={EnableAssemblySymmetry3D} initiallyCollapsed={true} nodeRef={pivot.cell.transform.ref} simpleApply={{ header: 'Enable', icon: Check }} />;
|
||||
return <ApplyActionControl state={pivot.cell.parent} action={EnableAssemblySymmetry3D} initiallyCollapsed={true} nodeRef={pivot.cell.transform.ref} simpleApply={{ header: 'Enable', icon: CheckSvg }} />;
|
||||
}
|
||||
|
||||
renderNoSymmetries() {
|
||||
|
||||
@@ -362,10 +362,19 @@ namespace Canvas3D {
|
||||
|
||||
camera.setState({ radiusMax: scene.boundingSphere.radius }, 0);
|
||||
reprCount.next(reprRenderObjects.size);
|
||||
if (isDebugMode) consoleStats();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function consoleStats() {
|
||||
console.table(scene.renderables.map(r => ({
|
||||
drawCount: r.values.drawCount.ref.value,
|
||||
instanceCount: r.values.instanceCount.ref.value,
|
||||
materialId: r.materialId,
|
||||
})));
|
||||
}
|
||||
|
||||
function add(repr: Representation.Any) {
|
||||
registerAutoUpdate(repr);
|
||||
|
||||
@@ -384,6 +393,7 @@ namespace Canvas3D {
|
||||
reprRenderObjects.set(repr, newRO);
|
||||
|
||||
scene.update(repr.renderObjects, false);
|
||||
if (isDebugMode) consoleStats();
|
||||
}
|
||||
|
||||
function remove(repr: Representation.Any) {
|
||||
@@ -394,6 +404,7 @@ namespace Canvas3D {
|
||||
renderObjects.forEach(o => scene.remove(o));
|
||||
reprRenderObjects.delete(repr);
|
||||
scene.update(repr.renderObjects, false, true);
|
||||
if (isDebugMode) consoleStats();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,5 +207,6 @@ export namespace Points {
|
||||
!props.pointFilledCircle ||
|
||||
(props.pointFilledCircle && props.pointEdgeBleach === 0)
|
||||
);
|
||||
state.writeDepth = state.opaque;
|
||||
}
|
||||
}
|
||||
@@ -283,6 +283,7 @@ export namespace Text {
|
||||
BaseGeometry.updateRenderableState(state, props);
|
||||
state.pickable = false;
|
||||
state.opaque = false;
|
||||
state.writeDepth = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { SubstitutionMatrix, SubstitutionMatrices, SubstitutionMatrixData } from
|
||||
const DefaultAlignmentOptions = {
|
||||
gapPenalty: -11,
|
||||
gapExtensionPenalty: -1,
|
||||
substMatrix: 'blosum62' as SubstitutionMatrix
|
||||
substMatrix: 'default' as SubstitutionMatrix | 'default'
|
||||
};
|
||||
export type AlignmentOptions = typeof DefaultAlignmentOptions;
|
||||
|
||||
@@ -22,7 +22,7 @@ export function align(seqA: ArrayLike<string>, seqB: ArrayLike<string>, options:
|
||||
|
||||
class Alignment {
|
||||
readonly gapPenalty: number; readonly gapExtensionPenalty: number
|
||||
readonly substMatrix: SubstitutionMatrixData
|
||||
readonly substMatrix: SubstitutionMatrixData | undefined
|
||||
|
||||
readonly n: number; readonly m: number
|
||||
readonly S: number[][] = []; readonly V: number[][] = []; readonly H: number[][] = []
|
||||
@@ -30,7 +30,7 @@ class Alignment {
|
||||
constructor (readonly seqA: ArrayLike<string>, readonly seqB: ArrayLike<string>, options: AlignmentOptions) {
|
||||
this.gapPenalty = options.gapPenalty;
|
||||
this.gapExtensionPenalty = options.gapExtensionPenalty;
|
||||
this.substMatrix = SubstitutionMatrices[options.substMatrix];
|
||||
this.substMatrix = options.substMatrix === 'default' ? undefined : SubstitutionMatrices[options.substMatrix];
|
||||
|
||||
this.n = this.seqA.length;
|
||||
this.m = this.seqB.length;
|
||||
@@ -61,22 +61,19 @@ class Alignment {
|
||||
}
|
||||
|
||||
private makeScoreFn () {
|
||||
const seq1 = this.seqA;
|
||||
const seq2 = this.seqB;
|
||||
|
||||
const substMatrix = this.substMatrix;
|
||||
const { seqA, seqB, substMatrix } = this;
|
||||
|
||||
if (substMatrix) {
|
||||
return function score (i: number, j: number) {
|
||||
const c1 = seq1[i];
|
||||
const c2 = seq2[j];
|
||||
return substMatrix[c1]?.[c2] ?? -4;
|
||||
const cA = seqA[i];
|
||||
const cB = seqB[j];
|
||||
return substMatrix[cA]?.[cB] ?? -4;
|
||||
};
|
||||
} else {
|
||||
return function scoreNoSubstMat (i: number, j: number) {
|
||||
const c1 = seq1[i];
|
||||
const c2 = seq2[j];
|
||||
return c1 === c2 ? 5 : -3;
|
||||
const cA = seqA[i];
|
||||
const cB = seqB[j];
|
||||
return cA === cB ? 5 : -3;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,26 @@ namespace AlignSequences {
|
||||
|
||||
function createSeqIdIndicesMap(element: StructureElement.Loci.Element) {
|
||||
const seqIds = new Map<number, StructureElement.UnitIndex[]>();
|
||||
if (!Unit.isAtomic(element.unit)) return seqIds;
|
||||
|
||||
const { label_seq_id } = element.unit.model.atomicHierarchy.residues;
|
||||
const { residueIndex } = element.unit;
|
||||
for (let i = 0, il = OrderedSet.size(element.indices); i < il; ++i) {
|
||||
const uI = OrderedSet.getAt(element.indices, i);
|
||||
const eI = element.unit.elements[uI];
|
||||
const seqId = label_seq_id.value(residueIndex[eI]);
|
||||
if (seqIds.has(seqId)) seqIds.get(seqId)!.push(uI);
|
||||
else seqIds.set(seqId, [uI]);
|
||||
if (Unit.isAtomic(element.unit)) {
|
||||
const { label_seq_id } = element.unit.model.atomicHierarchy.residues;
|
||||
const { residueIndex } = element.unit;
|
||||
for (let i = 0, il = OrderedSet.size(element.indices); i < il; ++i) {
|
||||
const uI = OrderedSet.getAt(element.indices, i);
|
||||
const eI = element.unit.elements[uI];
|
||||
const seqId = label_seq_id.value(residueIndex[eI]);
|
||||
if (seqIds.has(seqId)) seqIds.get(seqId)!.push(uI);
|
||||
else seqIds.set(seqId, [uI]);
|
||||
}
|
||||
} else if (Unit.isCoarse(element.unit)) {
|
||||
const { seq_id_begin } = Unit.isSpheres(element.unit)
|
||||
? element.unit.model.coarseHierarchy.spheres
|
||||
: element.unit.model.coarseHierarchy.gaussians;
|
||||
for (let i = 0, il = OrderedSet.size(element.indices); i < il; ++i) {
|
||||
const uI = OrderedSet.getAt(element.indices, i);
|
||||
const eI = element.unit.elements[uI];
|
||||
const seqId = seq_id_begin.value(eI);
|
||||
seqIds.set(seqId, [uI]);
|
||||
}
|
||||
}
|
||||
return seqIds;
|
||||
}
|
||||
|
||||
@@ -102,6 +102,10 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
|
||||
if (added) continue;
|
||||
}
|
||||
|
||||
// ignore atoms with zero occupancy (assuming they are not actually atoms)
|
||||
const occA = occupancyA.value(aI);
|
||||
if (hasOccupancy && occA === 0) continue;
|
||||
|
||||
const { indices, count, squaredDistances } = lookup3d.find(imageA[0], imageA[1], imageA[2], MAX_RADIUS);
|
||||
if (count === 0) continue;
|
||||
|
||||
@@ -112,7 +116,6 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
|
||||
const metalA = MetalsSet.has(aeI);
|
||||
const atomIdA = label_atom_idA.value(aI);
|
||||
const compIdA = label_comp_idA.value(residueIndexA[aI]);
|
||||
const occA = occupancyA.value(aI);
|
||||
|
||||
for (let ni = 0; ni < count; ni++) {
|
||||
const _bI = indices[ni] as StructureElement.UnitIndex;
|
||||
|
||||
@@ -39,6 +39,7 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni
|
||||
const atomCount = unit.elements.length;
|
||||
const { elements: atoms, residueIndex, chainIndex } = unit;
|
||||
const { type_symbol, label_atom_id, label_alt_id } = unit.model.atomicHierarchy.atoms;
|
||||
const { occupancy } = unit.model.atomicConformation;
|
||||
const { label_comp_id, label_seq_id } = unit.model.atomicHierarchy.residues;
|
||||
const { index } = unit.model.atomicHierarchy;
|
||||
const { byEntityKey } = unit.model.sequence;
|
||||
@@ -116,6 +117,9 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni
|
||||
}
|
||||
lastResidue = raI;
|
||||
|
||||
// ignore atoms with zero occupancy (assuming they are not actually atoms)
|
||||
if (occupancy.isDefined && occupancy.value(aI) === 0) continue;
|
||||
|
||||
const aeI = getElementIdx(type_symbol.value(aI));
|
||||
const atomIdA = label_atom_id.value(aI);
|
||||
const componentPairs = componentMap ? componentMap.get(atomIdA) : void 0;
|
||||
|
||||
@@ -9,6 +9,7 @@ import { MinimizeRmsd } from '../../../../mol-math/linear-algebra/3d/minimize-rm
|
||||
import StructureElement from '../element';
|
||||
import { OrderedSet } from '../../../../mol-data/int';
|
||||
import { AlignSequences } from '../../../sequence/alignment/sequence';
|
||||
import StructureProperties from '../properties';
|
||||
|
||||
export function superpose(xs: StructureElement.Loci[]): MinimizeRmsd.Result[] {
|
||||
const ret: MinimizeRmsd.Result[] = [];
|
||||
@@ -31,16 +32,21 @@ export function superpose(xs: StructureElement.Loci[]): MinimizeRmsd.Result[] {
|
||||
}
|
||||
|
||||
type AlignAndSuperposeResult = MinimizeRmsd.Result & { alignmentScore: number };
|
||||
const reProtein = /(polypeptide|cyclic-pseudo-peptide)/i;
|
||||
|
||||
export function alignAndSuperpose(xs: StructureElement.Loci[]): AlignAndSuperposeResult[] {
|
||||
const ret: AlignAndSuperposeResult[] = [];
|
||||
if (xs.length <= 0) return ret;
|
||||
|
||||
const l = StructureElement.Loci.getFirstLocation(xs[0])!;
|
||||
const subtype = StructureProperties.entity.subtype(l);
|
||||
const substMatrix = subtype.match(reProtein) ? 'blosum62' : 'default';
|
||||
|
||||
for (let i = 1; i < xs.length; i++) {
|
||||
const { a, b, score } = AlignSequences.compute({
|
||||
a: xs[0].elements[0],
|
||||
b: xs[i].elements[0]
|
||||
});
|
||||
b: xs[i].elements[0],
|
||||
}, { substMatrix });
|
||||
|
||||
const lociA = StructureElement.Loci(xs[0].structure, [a]);
|
||||
const lociB = StructureElement.Loci(xs[i].structure, [b]);
|
||||
|
||||
@@ -61,10 +61,6 @@ const DownloadStructure = StateAction.build({
|
||||
}, { pivot: 'id' }),
|
||||
options
|
||||
}, { isFlat: true, label: 'PDBDEV' }),
|
||||
'bcif-static': PD.Group({
|
||||
id: PD.Text('1tqn', { label: 'PDB Id(s)', description: 'One or more comma/space separated PDB ids.' }),
|
||||
options
|
||||
}, { isFlat: true, label: 'BinaryCIF (static PDBe Updated)' }),
|
||||
'swissmodel': PD.Group({
|
||||
id: PD.Text('Q9Y2I8', { label: 'UniProtKB AC(s)', description: 'One or more comma/space separated ACs.' }),
|
||||
options
|
||||
@@ -119,10 +115,6 @@ const DownloadStructure = StateAction.build({
|
||||
);
|
||||
asTrajectory = !!src.params.options.asTrajectory;
|
||||
break;
|
||||
case 'bcif-static':
|
||||
downloadParams = getDownloadParams(src.params.id, id => `https://webchem.ncbr.muni.cz/ModelServer/static/bcif/${id.toLowerCase()}`, id => `BinaryCIF: ${id}`, true);
|
||||
asTrajectory = !!src.params.options.asTrajectory;
|
||||
break;
|
||||
case 'swissmodel':
|
||||
downloadParams = getDownloadParams(src.params.id, id => `https://swissmodel.expasy.org/repository/uniprot/${id.toUpperCase()}.pdb`, id => `SWISS-MODEL: ${id}`, false);
|
||||
asTrajectory = !!src.params.options.asTrajectory;
|
||||
|
||||
@@ -90,7 +90,7 @@ export class StructureBuilder {
|
||||
const model = StateObjectRef.resolveAndCheck(state, modelRef);
|
||||
if (model) {
|
||||
const symm = ModelSymmetry.Provider.get(model.obj?.data!);
|
||||
if (!symm || symm?.assemblies.length === 0) params = { name: 'deposited', params: { } };
|
||||
if (!symm || symm?.assemblies.length === 0) params = { name: 'model', params: { } };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ const defaultPreset = TrajectoryHierarchyPresetProvider({
|
||||
id: 'preset-trajectory-default',
|
||||
display: {
|
||||
name: 'Default (Assembly)', group: 'Preset',
|
||||
description: 'Shows the first assembly or, if that is unavailable, the first deposited model.'
|
||||
description: 'Shows the first assembly or, if that is unavailable, the first model.'
|
||||
},
|
||||
isApplicable: o => {
|
||||
return true;
|
||||
@@ -93,7 +93,7 @@ const allModels = TrajectoryHierarchyPresetProvider({
|
||||
for (let i = 0; i < tr.length; i++) {
|
||||
const model = await builder.createModel(trajectory, { modelIndex: i });
|
||||
const modelProperties = await builder.insertModelProperties(model, params.modelProperties, { isCollapsed: true });
|
||||
const structure = await builder.createStructure(modelProperties || model, { name: 'deposited', params: {} });
|
||||
const structure = await builder.createStructure(modelProperties || model, { name: 'model', params: {} });
|
||||
const structureProperties = await builder.insertStructureProperties(structure, params.structureProperties);
|
||||
|
||||
models.push(model);
|
||||
|
||||
@@ -17,7 +17,7 @@ import { PluginStateObject as SO } from '../objects';
|
||||
import { ModelSymmetry } from '../../mol-model-formats/structure/property/symmetry';
|
||||
|
||||
export namespace RootStructureDefinition {
|
||||
export function getParams(model?: Model, defaultValue?: 'auto' | 'deposited' | 'assembly' | 'symmetry' | 'symmetry-mates' | 'symmetry-assembly') {
|
||||
export function getParams(model?: Model, defaultValue?: 'auto' | 'model' | 'assembly' | 'symmetry' | 'symmetry-mates' | 'symmetry-assembly') {
|
||||
const symmetry = model && ModelSymmetry.Provider.get(model);
|
||||
|
||||
const assemblyIds = symmetry ? symmetry.assemblies.map(a => [a.id, `${a.id}: ${stringToWords(a.details)}`] as [string, string]) : [];
|
||||
@@ -41,7 +41,7 @@ export namespace RootStructureDefinition {
|
||||
|
||||
const modes = {
|
||||
auto: PD.EmptyGroup(),
|
||||
deposited: PD.EmptyGroup(),
|
||||
model: PD.EmptyGroup(),
|
||||
assembly: PD.Group({
|
||||
id: PD.Optional(model
|
||||
? PD.Select(assemblyIds.length ? assemblyIds[0][0] : '', assemblyIds, { label: 'Asm Id', description: 'Assembly Id' })
|
||||
@@ -75,7 +75,7 @@ export namespace RootStructureDefinition {
|
||||
options.push(['auto', 'Auto']);
|
||||
}
|
||||
|
||||
options.push(['deposited', 'Deposited']);
|
||||
options.push(['model', 'Model']);
|
||||
|
||||
if (assemblyIds.length > 0) {
|
||||
options.push(['assembly', 'Assembly']);
|
||||
@@ -88,7 +88,7 @@ export namespace RootStructureDefinition {
|
||||
}
|
||||
|
||||
return {
|
||||
type: PD.MappedStatic(defaultValue || 'deposited', modes, { options })
|
||||
type: PD.MappedStatic(defaultValue || 'model', modes, { options })
|
||||
};
|
||||
}
|
||||
|
||||
@@ -110,19 +110,17 @@ export namespace RootStructureDefinition {
|
||||
}
|
||||
|
||||
if (!symmetry || symmetry.assemblies.length === 0) {
|
||||
if (id !== 'deposited') {
|
||||
plugin.log.warn(`Model '${model.entryId}' has no assembly, returning deposited structure.`);
|
||||
}
|
||||
plugin.log.warn(`Model '${model.entryId}' has no assembly, returning model structure.`);
|
||||
} else {
|
||||
asm = Symmetry.findAssembly(model, id || '');
|
||||
if (!asm) {
|
||||
plugin.log.warn(`Model '${model.entryId}' has no assembly called '${id}', returning deposited structure.`);
|
||||
plugin.log.warn(`Model '${model.entryId}' has no assembly called '${id}', returning model structure.`);
|
||||
}
|
||||
}
|
||||
|
||||
const base = Structure.ofModel(model);
|
||||
if (!asm) {
|
||||
const label = { label: 'Deposited', description: Structure.elementDescription(base) };
|
||||
const label = { label: 'Model', description: Structure.elementDescription(base) };
|
||||
return new SO.Molecule.Structure(base, label);
|
||||
}
|
||||
|
||||
@@ -155,14 +153,14 @@ export namespace RootStructureDefinition {
|
||||
|
||||
export async function create(plugin: PluginContext, ctx: RuntimeContext, model: Model, params?: Params): Promise<SO.Molecule.Structure> {
|
||||
const symmetry = ModelSymmetry.Provider.get(model);
|
||||
if (!symmetry || !params || params.name === 'deposited') {
|
||||
if (!symmetry || !params || params.name === 'model') {
|
||||
const s = Structure.ofModel(model);
|
||||
return new SO.Molecule.Structure(s, { label: 'Deposited', description: Structure.elementDescription(s) });
|
||||
return new SO.Molecule.Structure(s, { label: 'Model', description: Structure.elementDescription(s) });
|
||||
}
|
||||
if (params.name === 'auto') {
|
||||
if (symmetry.assemblies.length === 0) {
|
||||
const s = Structure.ofModel(model);
|
||||
return new SO.Molecule.Structure(s, { label: 'Deposited', description: Structure.elementDescription(s) });
|
||||
return new SO.Molecule.Structure(s, { label: 'Model', description: Structure.elementDescription(s) });
|
||||
} else {
|
||||
return buildAssembly(plugin, ctx, model);
|
||||
}
|
||||
|
||||
@@ -135,6 +135,17 @@ const _nucleiEntityTest = MS.core.logic.and([
|
||||
])
|
||||
]);
|
||||
|
||||
/**
|
||||
* this is to get non-polymer and peptide terminus components in polymer entities,
|
||||
* - non-polymer, e.g. PXZ in 4HIV or generally ACE
|
||||
* - carboxy terminus, e.g. FC0 in 4BP9, or ETA in 6DDE
|
||||
* - amino terminus, e.g. ARF in 3K4V, or 4MM in 3EGV
|
||||
*/
|
||||
const _nonPolymerResidueTest = MS.core.str.match([
|
||||
MS.re('non-polymer|(amino|carboxy) terminus|peptide-like', 'i'),
|
||||
MS.ammp('chemCompType')
|
||||
]);
|
||||
|
||||
// TODO maybe pre-calculate backbone atom properties
|
||||
const backbone = StructureSelectionQuery('Backbone', MS.struct.modifier.union([
|
||||
MS.struct.combinator.merge([
|
||||
@@ -142,6 +153,7 @@ const backbone = StructureSelectionQuery('Backbone', MS.struct.modifier.union([
|
||||
MS.struct.generator.atomGroups({
|
||||
'entity-test': _proteinEntityTest,
|
||||
'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
|
||||
'residue-test': MS.core.logic.not([_nonPolymerResidueTest]),
|
||||
'atom-test': MS.core.set.has([MS.set(...SetUtils.toArray(ProteinBackboneAtoms)), MS.ammp('label_atom_id')])
|
||||
})
|
||||
]),
|
||||
@@ -149,6 +161,7 @@ const backbone = StructureSelectionQuery('Backbone', MS.struct.modifier.union([
|
||||
MS.struct.generator.atomGroups({
|
||||
'entity-test': _nucleiEntityTest,
|
||||
'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
|
||||
'residue-test': MS.core.logic.not([_nonPolymerResidueTest]),
|
||||
'atom-test': MS.core.set.has([MS.set(...SetUtils.toArray(NucleicBackboneAtoms)), MS.ammp('label_atom_id')])
|
||||
})
|
||||
])
|
||||
@@ -162,6 +175,7 @@ const sidechain = StructureSelectionQuery('Sidechain', MS.struct.modifier.union(
|
||||
MS.struct.generator.atomGroups({
|
||||
'entity-test': _proteinEntityTest,
|
||||
'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
|
||||
'residue-test': MS.core.logic.not([_nonPolymerResidueTest]),
|
||||
'atom-test': MS.core.logic.or([
|
||||
MS.core.logic.not([
|
||||
MS.core.set.has([MS.set(...SetUtils.toArray(ProteinBackboneAtoms)), MS.ammp('label_atom_id')])
|
||||
@@ -173,6 +187,7 @@ const sidechain = StructureSelectionQuery('Sidechain', MS.struct.modifier.union(
|
||||
MS.struct.generator.atomGroups({
|
||||
'entity-test': _nucleiEntityTest,
|
||||
'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
|
||||
'residue-test': MS.core.logic.not([_nonPolymerResidueTest]),
|
||||
'atom-test': MS.core.logic.or([
|
||||
MS.core.logic.not([
|
||||
MS.core.set.has([MS.set(...SetUtils.toArray(NucleicBackboneAtoms)), MS.ammp('label_atom_id')])
|
||||
@@ -190,6 +205,7 @@ const sidechainWithTrace = StructureSelectionQuery('Sidechain with Trace', MS.st
|
||||
MS.struct.generator.atomGroups({
|
||||
'entity-test': _proteinEntityTest,
|
||||
'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
|
||||
'residue-test': MS.core.logic.not([_nonPolymerResidueTest]),
|
||||
'atom-test': MS.core.logic.or([
|
||||
MS.core.logic.not([
|
||||
MS.core.set.has([MS.set(...SetUtils.toArray(ProteinBackboneAtoms)), MS.ammp('label_atom_id')])
|
||||
@@ -206,6 +222,7 @@ const sidechainWithTrace = StructureSelectionQuery('Sidechain with Trace', MS.st
|
||||
MS.struct.generator.atomGroups({
|
||||
'entity-test': _nucleiEntityTest,
|
||||
'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
|
||||
'residue-test': MS.core.logic.not([_nonPolymerResidueTest]),
|
||||
'atom-test': MS.core.logic.or([
|
||||
MS.core.logic.not([
|
||||
MS.core.set.has([MS.set(...SetUtils.toArray(NucleicBackboneAtoms)), MS.ammp('label_atom_id')])
|
||||
@@ -296,18 +313,11 @@ const ligand = StructureSelectionQuery('Ligand', MS.struct.modifier.union([
|
||||
])
|
||||
})
|
||||
]),
|
||||
// this is to get non-polymer and peptide terminus components in polymer entities,
|
||||
// - non-polymer, e.g. PXZ in 4HIV or generally ACE
|
||||
// - carboxy terminus, e.g. FC0 in 4BP9, or ETA in 6DDE
|
||||
// - amino terminus, e.g. ARF in 3K4V, or 4MM in 3EGV
|
||||
MS.struct.modifier.union([
|
||||
MS.struct.generator.atomGroups({
|
||||
'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer']),
|
||||
'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']),
|
||||
'residue-test': MS.core.str.match([
|
||||
MS.re('non-polymer|(amino|carboxy) terminus|peptide-like', 'i'),
|
||||
MS.ammp('chemCompType')
|
||||
])
|
||||
'residue-test': _nonPolymerResidueTest
|
||||
})
|
||||
])
|
||||
]),
|
||||
|
||||
@@ -204,9 +204,10 @@ namespace InteractivityManager {
|
||||
}
|
||||
|
||||
selectOnly(current: Representation.Loci, applyGranularity = true) {
|
||||
this.deselectAll();
|
||||
const normalized = this.normalizedLoci(current, applyGranularity);
|
||||
if (StructureElement.Loci.is(normalized.loci)) {
|
||||
// only deselect for the structure of the given loci
|
||||
this.deselect({ loci: Structure.toStructureElementLoci(normalized.loci.structure), repr: normalized.repr }, false);
|
||||
this.sel.modify('set', normalized.loci);
|
||||
}
|
||||
this.mark(normalized, MarkerAction.Select);
|
||||
|
||||
@@ -231,6 +231,8 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
|
||||
|
||||
if (PluginStateSnapshotManager.isStateSnapshot(snapshot)) {
|
||||
return this.setStateSnapshot(snapshot);
|
||||
} else if (PluginStateSnapshotManager.isStateSnapshot(snapshot.data)) {
|
||||
return this.setStateSnapshot(snapshot.data);
|
||||
} else {
|
||||
this.plugin.state.setSnapshot(snapshot);
|
||||
}
|
||||
@@ -330,7 +332,7 @@ namespace PluginStateSnapshotManager {
|
||||
snapshot: PluginState.Snapshot
|
||||
}
|
||||
|
||||
export function Entry(snapshot: PluginState.Snapshot, params: {name?: string, description?: string }): Entry {
|
||||
export function Entry(snapshot: PluginState.Snapshot, params: { name?: string, description?: string }): Entry {
|
||||
return { timestamp: +new Date(), snapshot, ...params };
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@ import { EmptyLoci, Loci } from '../../../mol-model/loci';
|
||||
import { Structure, StructureElement, StructureSelection } from '../../../mol-model/structure';
|
||||
import { Boundary } from '../../../mol-model/structure/structure/util/boundary';
|
||||
import { PluginContext } from '../../../mol-plugin/context';
|
||||
import { StateObject, StateObjectRef } from '../../../mol-state';
|
||||
import { StateObjectRef } from '../../../mol-state';
|
||||
import { Task } from '../../../mol-task';
|
||||
import { structureElementStatsLabel } from '../../../mol-theme/label';
|
||||
import { arrayRemoveAtInPlace } from '../../../mol-util/array';
|
||||
import { StatefulPluginComponent } from '../../component';
|
||||
import { StructureSelectionQuery } from '../../helpers/structure-selection-query';
|
||||
import { PluginStateObject } from '../../objects';
|
||||
import { PluginStateObject as PSO } from '../../objects';
|
||||
import { UUID } from '../../../mol-util';
|
||||
import { StructureRef } from './hierarchy-state';
|
||||
|
||||
@@ -46,7 +46,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
|
||||
}
|
||||
}
|
||||
|
||||
private referenceLoci: Loci | undefined
|
||||
private referenceLoci: StructureElement.Loci | undefined
|
||||
|
||||
get entries() { return this.state.entries; }
|
||||
get additionsHistory() { return this.state.additionsHistory; }
|
||||
@@ -57,7 +57,8 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
|
||||
}
|
||||
|
||||
private getEntry(s: Structure) {
|
||||
const cell = this.plugin.helpers.substructureParent.get(s);
|
||||
// ignore decorators to get stable ref
|
||||
const cell = this.plugin.helpers.substructureParent.get(s, true);
|
||||
if (!cell) return;
|
||||
const ref = cell.transform.ref;
|
||||
if (!this.entries.has(ref)) {
|
||||
@@ -144,26 +145,34 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
|
||||
return !StructureElement.Loci.areEqual(sel, entry.selection);
|
||||
}
|
||||
|
||||
modifyHistory(entry: StructureSelectionHistoryEntry, action: 'remove' | 'up' | 'down', modulus?: number) {
|
||||
const idx = this.additionsHistory.indexOf(entry);
|
||||
modifyHistory(entry: StructureSelectionHistoryEntry, action: 'remove' | 'up' | 'down', modulus?: number, groupByStructure = false) {
|
||||
const history = this.additionsHistory;
|
||||
const idx = history.indexOf(entry);
|
||||
if (idx < 0) return;
|
||||
|
||||
let swapWith: number | undefined = void 0;
|
||||
|
||||
switch (action) {
|
||||
case 'remove': arrayRemoveAtInPlace(this.additionsHistory, idx); break;
|
||||
case 'remove': arrayRemoveAtInPlace(history, idx); break;
|
||||
case 'up': swapWith = idx - 1; break;
|
||||
case 'down': swapWith = idx + 1; break;
|
||||
}
|
||||
|
||||
if (swapWith !== void 0) {
|
||||
const mod = modulus ? Math.min(this.additionsHistory.length, modulus) : this.additionsHistory.length;
|
||||
swapWith = swapWith % mod;
|
||||
if (swapWith < 0) swapWith += mod;
|
||||
const mod = modulus ? Math.min(history.length, modulus) : history.length;
|
||||
while (true) {
|
||||
swapWith = swapWith % mod;
|
||||
if (swapWith < 0) swapWith += mod;
|
||||
|
||||
const t = this.additionsHistory[idx];
|
||||
this.additionsHistory[idx] = this.additionsHistory[swapWith];
|
||||
this.additionsHistory[swapWith] = t;
|
||||
if (!groupByStructure || history[idx].loci.structure === history[swapWith].loci.structure) {
|
||||
const t = history[idx];
|
||||
history[idx] = history[swapWith];
|
||||
history[swapWith] = t;
|
||||
break;
|
||||
} else {
|
||||
swapWith += action === 'up' ? -1 : +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.events.additionsHistoryUpdated.next();
|
||||
@@ -205,32 +214,81 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
|
||||
}
|
||||
}
|
||||
|
||||
private onRemove(ref: string) {
|
||||
if (this.entries.has(ref)) {
|
||||
this.entries.delete(ref);
|
||||
this.clearHistory();
|
||||
this.referenceLoci = undefined;
|
||||
private clearHistoryForStructure(structure: Structure) {
|
||||
const historyEntryToRemove: StructureSelectionHistoryEntry[] = [];
|
||||
for (const e of this.state.additionsHistory) {
|
||||
if (e.loci.structure.root === structure.root) {
|
||||
historyEntryToRemove.push(e);
|
||||
}
|
||||
}
|
||||
for (const e of historyEntryToRemove) {
|
||||
this.modifyHistory(e, 'remove');
|
||||
}
|
||||
if (historyEntryToRemove.length !== 0) {
|
||||
this.events.additionsHistoryUpdated.next();
|
||||
}
|
||||
}
|
||||
|
||||
private onUpdate(ref: string, oldObj: StateObject | undefined, obj: StateObject) {
|
||||
if (!PluginStateObject.Molecule.Structure.is(obj)) return;
|
||||
|
||||
private onRemove(ref: string, obj: PSO.Molecule.Structure | undefined) {
|
||||
if (this.entries.has(ref)) {
|
||||
if (!PluginStateObject.Molecule.Structure.is(oldObj) || oldObj === obj || oldObj.data === obj.data) return;
|
||||
this.entries.delete(ref);
|
||||
if (obj?.data) {
|
||||
this.clearHistoryForStructure(obj.data);
|
||||
}
|
||||
if (this.referenceLoci?.structure === obj?.data) {
|
||||
this.referenceLoci = undefined;
|
||||
}
|
||||
this.state.stats = void 0;
|
||||
this.events.changed.next();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: property update the latest loci & reference loci
|
||||
this.state.additionsHistory = [];
|
||||
this.referenceLoci = undefined;
|
||||
private onUpdate(ref: string, oldObj: PSO.Molecule.Structure | undefined, obj: PSO.Molecule.Structure) {
|
||||
|
||||
// remap the old selection to be related to the new object if possible.
|
||||
if (Structure.areUnitAndIndicesEqual(oldObj.data, obj.data)) {
|
||||
this.entries.set(ref, remapSelectionEntry(this.entries.get(ref)!, obj.data));
|
||||
return;
|
||||
// no change to structure
|
||||
if (oldObj === obj || oldObj?.data === obj.data) return;
|
||||
|
||||
// ignore decorators to get stable ref
|
||||
const cell = this.plugin.helpers.substructureParent.get(obj.data, true);
|
||||
if (!cell) return;
|
||||
|
||||
ref = cell.transform.ref;
|
||||
if (!this.entries.has(ref)) return;
|
||||
|
||||
// use structure from last decorator as reference
|
||||
const structure = this.plugin.helpers.substructureParent.get(obj.data)?.obj?.data;
|
||||
if (!structure) return;
|
||||
|
||||
// oldObj is not defined for inserts (e.g. TransformStructureConformation)
|
||||
if (!oldObj || Structure.areUnitAndIndicesEqual(oldObj.data, obj.data)) {
|
||||
this.entries.set(ref, remapSelectionEntry(this.entries.get(ref)!, structure));
|
||||
|
||||
// remap referenceLoci & prevHighlight if needed and possible
|
||||
if (this.referenceLoci?.structure.root === structure.root) {
|
||||
this.referenceLoci = StructureElement.Loci.remap(this.referenceLoci, structure);
|
||||
}
|
||||
|
||||
// clear the selection
|
||||
this.entries.set(ref, new SelectionEntry(StructureElement.Loci(obj.data, [])));
|
||||
// remap history locis if needed and possible
|
||||
let changedHistory = false;
|
||||
for (const e of this.state.additionsHistory) {
|
||||
if (e.loci.structure.root === structure.root) {
|
||||
e.loci = StructureElement.Loci.remap(e.loci, structure);
|
||||
changedHistory = true;
|
||||
}
|
||||
}
|
||||
if (changedHistory) this.events.additionsHistoryUpdated.next();
|
||||
} else {
|
||||
// clear the selection for ref
|
||||
this.entries.set(ref, new SelectionEntry(StructureElement.Loci(structure, [])));
|
||||
|
||||
if (this.referenceLoci?.structure.root === structure.root) {
|
||||
this.referenceLoci = undefined;
|
||||
}
|
||||
|
||||
this.clearHistoryForStructure(structure);
|
||||
|
||||
this.state.stats = void 0;
|
||||
this.events.changed.next();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +350,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
|
||||
if (!xs) return;
|
||||
|
||||
const ref = this.referenceLoci;
|
||||
if (!ref || !StructureElement.Loci.is(ref) || ref.structure.root !== loci.structure.root) return;
|
||||
if (!ref || !StructureElement.Loci.is(ref) || ref.structure !== loci.structure) return;
|
||||
|
||||
let e: StructureElement.Loci['elements'][0] | undefined;
|
||||
for (const _e of ref.elements) {
|
||||
@@ -305,26 +363,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
|
||||
|
||||
if (xs.unit !== e.unit) return;
|
||||
|
||||
return getElementRange(loci.structure.root, e, xs);
|
||||
}
|
||||
|
||||
private prevHighlight: StructureElement.Loci | undefined = void 0;
|
||||
|
||||
accumulateInteractiveHighlight(loci: Loci) {
|
||||
if (StructureElement.Loci.is(loci)) {
|
||||
if (this.prevHighlight) {
|
||||
this.prevHighlight = StructureElement.Loci.union(this.prevHighlight, loci);
|
||||
} else {
|
||||
this.prevHighlight = loci;
|
||||
}
|
||||
}
|
||||
return this.prevHighlight;
|
||||
}
|
||||
|
||||
clearInteractiveHighlight() {
|
||||
const ret = this.prevHighlight;
|
||||
this.prevHighlight = void 0;
|
||||
return ret || EmptyLoci;
|
||||
return getElementRange(loci.structure, e, xs);
|
||||
}
|
||||
|
||||
/** Count of all selected elements */
|
||||
@@ -427,11 +466,11 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
|
||||
}));
|
||||
}
|
||||
|
||||
fromSelections(ref: StateObjectRef<PluginStateObject.Molecule.Structure.Selections>) {
|
||||
fromSelections(ref: StateObjectRef<PSO.Molecule.Structure.Selections>) {
|
||||
const cell = StateObjectRef.resolveAndCheck(this.plugin.state.data, ref);
|
||||
if (!cell || !cell.obj) return;
|
||||
|
||||
if (!PluginStateObject.Molecule.Structure.Selections.is(cell.obj)) {
|
||||
if (!PSO.Molecule.Structure.Selections.is(cell.obj)) {
|
||||
console.warn('fromSelections applied to wrong object type.', cell.obj);
|
||||
return;
|
||||
}
|
||||
@@ -445,8 +484,9 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
|
||||
constructor(private plugin: PluginContext) {
|
||||
super({ entries: new Map(), additionsHistory: [], stats: SelectionStats() });
|
||||
|
||||
plugin.state.data.events.object.removed.subscribe(e => this.onRemove(e.ref));
|
||||
plugin.state.data.events.object.updated.subscribe(e => this.onUpdate(e.ref, e.oldObj, e.obj));
|
||||
// listen to events from substructureParent helper to ensure it is updated
|
||||
plugin.helpers.substructureParent.events.removed.subscribe(e => this.onRemove(e.ref, e.obj));
|
||||
plugin.helpers.substructureParent.events.updated.subscribe(e => this.onUpdate(e.ref, e.oldObj, e.obj));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -371,7 +371,7 @@ const StructureFromTrajectory = PluginStateTransform.BuiltIn({
|
||||
type StructureFromModel = typeof StructureFromModel
|
||||
const StructureFromModel = PluginStateTransform.BuiltIn({
|
||||
name: 'structure-from-model',
|
||||
display: { name: 'Structure', description: 'Create a molecular structure (deposited, assembly, or symmetry) from the specified model.' },
|
||||
display: { name: 'Structure', description: 'Create a molecular structure (model, assembly, or symmetry) from the specified model.' },
|
||||
from: SO.Molecule.Model,
|
||||
to: SO.Molecule.Structure,
|
||||
params(a) { return RootStructureDefinition.getParams(a && a.data); }
|
||||
|
||||
@@ -42,7 +42,7 @@ const VolumeFromCcp4 = PluginStateTransform.BuiltIn({
|
||||
apply({ a, params }) {
|
||||
return Task.create('Create volume from CCP4/MRC/MAP', async ctx => {
|
||||
const volume = await volumeFromCcp4(a.data, { ...params, label: a.data.name || a.label }).runInContext(ctx);
|
||||
const props = { label: volume.label || 'Volume', description: 'Volume' };
|
||||
const props = { label: volume.label || 'Volume', description: `Volume ${a.data.header.NX}\u00D7${a.data.header.NX}\u00D7${a.data.header.NX}` };
|
||||
return new SO.Volume.Data(volume, props);
|
||||
});
|
||||
}
|
||||
@@ -63,7 +63,7 @@ const VolumeFromDsn6 = PluginStateTransform.BuiltIn({
|
||||
apply({ a, params }) {
|
||||
return Task.create('Create volume from DSN6/BRIX', async ctx => {
|
||||
const volume = await volumeFromDsn6(a.data, { ...params, label: a.data.name || a.label }).runInContext(ctx);
|
||||
const props = { label: volume.label || 'Volume', description: 'Volume' };
|
||||
const props = { label: volume.label || 'Volume', description: `Volume ${a.data.header.xExtent}\u00D7${a.data.header.yExtent}\u00D7${a.data.header.zExtent}` };
|
||||
return new SO.Volume.Data(volume, props);
|
||||
});
|
||||
}
|
||||
@@ -85,7 +85,7 @@ const VolumeFromCube = PluginStateTransform.BuiltIn({
|
||||
apply({ a, params }) {
|
||||
return Task.create('Create volume from Cube', async ctx => {
|
||||
const volume = await volumeFromCube(a.data, { ...params, label: a.data.name || a.label }).runInContext(ctx);
|
||||
const props = { label: volume.label || 'Volume', description: 'Volume' };
|
||||
const props = { label: volume.label || 'Volume', description: `Volume ${a.data.header.dim[0]}\u00D7${a.data.header.dim[1]}\u00D7${a.data.header.dim[2]}` };
|
||||
return new SO.Volume.Data(volume, props);
|
||||
});
|
||||
}
|
||||
@@ -102,8 +102,7 @@ const VolumeFromDx = PluginStateTransform.BuiltIn({
|
||||
return Task.create('Parse DX', async ctx => {
|
||||
console.log(a);
|
||||
const volume = await volumeFromDx(a.data, { label: a.data.name || a.label }).runInContext(ctx);
|
||||
console.log(volume);
|
||||
const props = { label: volume.label || 'Volume', description: 'Volume' };
|
||||
const props = { label: volume.label || 'Volume', description: `Volume ${a.data.header.dim[0]}\u00D7${a.data.header.dim[1]}\u00D7${a.data.header.dim[2]}` };
|
||||
return new SO.Volume.Data(volume, props);
|
||||
});
|
||||
}
|
||||
@@ -135,7 +134,8 @@ const VolumeFromDensityServerCif = PluginStateTransform.BuiltIn({
|
||||
if (!block) throw new Error(`Data block '${[header]}' not found.`);
|
||||
const densityServerCif = CIF.schema.densityServer(block);
|
||||
const volume = await volumeFromDensityServerData(densityServerCif).runInContext(ctx);
|
||||
const props = { label: densityServerCif.volume_data_3d_info.name.value(0), description: `${densityServerCif.volume_data_3d_info.name.value(0)}` };
|
||||
const [x, y, z] = volume.grid.cells.space.dimensions;
|
||||
const props = { label: densityServerCif.volume_data_3d_info.name.value(0), description: `Volume ${x}\u00D7${y}\u00D7${z}` };
|
||||
return new SO.Volume.Data(volume, props);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,9 +9,7 @@ import * as React from 'react';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { PluginContext } from '../mol-plugin/context';
|
||||
import { Button, ColorAccent } from './controls/common';
|
||||
import ArrowRight from '@material-ui/icons/ArrowRight';
|
||||
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
|
||||
import { Icon } from './controls/icons';
|
||||
import { Icon, ArrowRightSvg, ArrowDropDownSvg } from './controls/icons';
|
||||
|
||||
export const PluginReactContext = React.createContext(void 0 as any as PluginContext);
|
||||
|
||||
@@ -104,7 +102,7 @@ export abstract class CollapsableControls<P = {}, S = {}, SS = {}> extends Plugi
|
||||
|
||||
return <div className={wrapClass}>
|
||||
<div className='msp-transform-header'>
|
||||
<Button icon={this.state.brand ? void 0 : this.state.isCollapsed ? ArrowRight : ArrowDropDown} noOverflow onClick={this.toggleCollapsed}
|
||||
<Button icon={this.state.brand ? void 0 : this.state.isCollapsed ? ArrowRightSvg : ArrowDropDownSvg} noOverflow onClick={this.toggleCollapsed}
|
||||
className={this.state.brand ? `msp-transform-header-brand msp-transform-header-brand-${this.state.brand.accent}` : void 0} title={`Click to ${this.state.isCollapsed ? 'expand' : 'collapse'}`}>
|
||||
{/* {this.state.brand && <div className={`msp-accent-bg-${this.state.brand.accent}`}>{this.state.brand.svg ? <Icon svg={this.state.brand.svg} /> : this.state.brand.name}</div>} */}
|
||||
<Icon svg={this.state.brand?.svg} inline />
|
||||
|
||||
@@ -5,13 +5,6 @@
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import Build from '@material-ui/icons/Build';
|
||||
import NavigateBefore from '@material-ui/icons/NavigateBefore';
|
||||
import NavigateNext from '@material-ui/icons/NavigateNext';
|
||||
import PlayArrow from '@material-ui/icons/PlayArrow';
|
||||
import SkipPrevious from '@material-ui/icons/SkipPrevious';
|
||||
import Stop from '@material-ui/icons/Stop';
|
||||
import SubscriptionsOutlined from '@material-ui/icons/SubscriptionsOutlined';
|
||||
import * as React from 'react';
|
||||
import { UpdateTrajectory } from '../mol-plugin-state/actions/structure';
|
||||
import { LociLabel } from '../mol-plugin-state/manager/loci-label';
|
||||
@@ -22,7 +15,7 @@ import { PluginCommands } from '../mol-plugin/commands';
|
||||
import { StateTransformer } from '../mol-state';
|
||||
import { PluginUIComponent } from './base';
|
||||
import { IconButton } from './controls/common';
|
||||
import { Icon } from './controls/icons';
|
||||
import { Icon, NavigateBeforeSvg, NavigateNextSvg, SkipPreviousSvg, StopSvg, PlayArrowSvg, SubscriptionsOutlinedSvg, BuildSvg } from './controls/icons';
|
||||
import { AnimationControls } from './state/animation';
|
||||
import { StructureComponentControls } from './structure/components';
|
||||
import { StructureMeasurementsControls } from './structure/measurements';
|
||||
@@ -97,9 +90,9 @@ export class TrajectoryViewportControls extends PluginUIComponent<{}, { show: bo
|
||||
if (!this.state.show || (isAnimating && !this.state.label)) return null;
|
||||
|
||||
return <div className='msp-traj-controls'>
|
||||
{!isAnimating && <IconButton svg={SkipPrevious} title='First Model' onClick={this.reset} disabled={isAnimating} />}
|
||||
{!isAnimating && <IconButton svg={NavigateBefore} title='Previous Model' onClick={this.prev} disabled={isAnimating} />}
|
||||
{!isAnimating && <IconButton svg={NavigateNext} title='Next Model' onClick={this.next} disabled={isAnimating} />}
|
||||
{!isAnimating && <IconButton svg={SkipPreviousSvg} title='First Model' onClick={this.reset} disabled={isAnimating} />}
|
||||
{!isAnimating && <IconButton svg={NavigateBeforeSvg} title='Previous Model' onClick={this.prev} disabled={isAnimating} />}
|
||||
{!isAnimating && <IconButton svg={NavigateNextSvg} title='Next Model' onClick={this.next} disabled={isAnimating} />}
|
||||
{!!this.state.label && <span>{this.state.label}</span> }
|
||||
</div>;
|
||||
}
|
||||
@@ -187,11 +180,11 @@ export class StateSnapshotViewportControls extends PluginUIComponent<{}, { isBus
|
||||
{!current && <option key='none' value='none'></option>}
|
||||
{snapshots.state.entries.valueSeq().map((e, i) => <option key={e!.snapshot.id} value={e!.snapshot.id}>{`[${i! + 1}/${count}]`} {e!.name || new Date(e!.timestamp).toLocaleString()}</option>)}
|
||||
</select>
|
||||
<IconButton svg={isPlaying ? Stop : PlayArrow} title={isPlaying ? 'Pause' : 'Cycle States'} onClick={this.togglePlay}
|
||||
<IconButton svg={isPlaying ? StopSvg : PlayArrowSvg} title={isPlaying ? 'Pause' : 'Cycle States'} onClick={this.togglePlay}
|
||||
disabled={isPlaying ? false : this.state.isBusy} />
|
||||
{!isPlaying && <>
|
||||
<IconButton svg={NavigateBefore} title='Previous State' onClick={this.prev} disabled={this.state.isBusy || isPlaying} />
|
||||
<IconButton svg={NavigateNext} title='Next State' onClick={this.next} disabled={this.state.isBusy || isPlaying} />
|
||||
<IconButton svg={NavigateBeforeSvg} title='Previous State' onClick={this.prev} disabled={this.state.isBusy || isPlaying} />
|
||||
<IconButton svg={NavigateNextSvg} title='Next State' onClick={this.next} disabled={this.state.isBusy || isPlaying} />
|
||||
</>}
|
||||
</div>;
|
||||
}
|
||||
@@ -229,7 +222,7 @@ export class AnimationViewportControls extends PluginUIComponent<{}, { isEmpty:
|
||||
return <div className='msp-animation-viewport-controls'>
|
||||
<div>
|
||||
<div className='msp-semi-transparent-background' />
|
||||
<IconButton svg={isAnimating || isPlaying ? Stop : SubscriptionsOutlined} transparent title={isAnimating ? 'Stop' : 'Select Animation'}
|
||||
<IconButton svg={isAnimating || isPlaying ? StopSvg : SubscriptionsOutlinedSvg} transparent title={isAnimating ? 'Stop' : 'Select Animation'}
|
||||
onClick={isAnimating || isPlaying ? this.stop : this.toggleExpanded} toggleState={this.state.isExpanded}
|
||||
disabled={isAnimating || isPlaying ? false : this.state.isBusy || this.state.isPlaying || this.state.isEmpty} />
|
||||
</div>
|
||||
@@ -293,7 +286,7 @@ export class CustomStructureControls extends PluginUIComponent<{ initiallyCollap
|
||||
export class DefaultStructureTools extends PluginUIComponent {
|
||||
render() {
|
||||
return <>
|
||||
<div className='msp-section-header'><Icon svg={Build} />Structure Tools</div>
|
||||
<div className='msp-section-header'><Icon svg={BuildSvg} />Structure Tools</div>
|
||||
|
||||
<StructureSourceControls />
|
||||
<StructureMeasurementsControls />
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
import * as React from 'react';
|
||||
import { ParamDefinition } from '../../mol-util/param-definition';
|
||||
import { Button, ControlGroup } from './common';
|
||||
import ArrowRight from '@material-ui/icons/ArrowRight';
|
||||
import Check from '@material-ui/icons/Check';
|
||||
import Close from '@material-ui/icons/Close';
|
||||
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
|
||||
import { CloseSvg, ArrowDropDownSvg, ArrowRightSvg, CheckSvg } from './icons';
|
||||
|
||||
export class ActionMenu extends React.PureComponent<ActionMenu.Props> {
|
||||
hide = () => this.props.onSelect(void 0)
|
||||
@@ -20,7 +17,7 @@ export class ActionMenu extends React.PureComponent<ActionMenu.Props> {
|
||||
const cmd = this.props;
|
||||
const section = <Section items={cmd.items} onSelect={cmd.onSelect} current={cmd.current} multiselect={this.props.multiselect} noOffset={this.props.noOffset} noAccent={this.props.noAccent} />;
|
||||
return <div className={`msp-action-menu-options${cmd.header ? '' : ' msp-action-menu-options-no-header'}`}>
|
||||
{cmd.header && <ControlGroup header={cmd.header} title={cmd.title} initialExpanded={true} hideExpander={true} hideOffset onHeaderClick={this.hide} topRightIcon={Close}>
|
||||
{cmd.header && <ControlGroup header={cmd.header} title={cmd.title} initialExpanded={true} hideExpander={true} hideOffset onHeaderClick={this.hide} topRightIcon={CloseSvg}>
|
||||
{section}
|
||||
</ControlGroup>}
|
||||
{!cmd.header && section}
|
||||
@@ -229,13 +226,13 @@ class Section extends React.PureComponent<SectionProps, SectionState> {
|
||||
const { header, hasCurrent } = this.state;
|
||||
|
||||
return <div className='msp-flex-row msp-control-group-header'>
|
||||
<Button icon={this.state.isExpanded ? ArrowDropDown : ArrowRight} flex noOverflow onClick={this.toggleExpanded} title={`Click to ${this.state.isExpanded ? 'collapse' : 'expand'}.${header?.description ? ` ${header?.description}` : ''}`}>
|
||||
<Button icon={this.state.isExpanded ? ArrowDropDownSvg : ArrowRightSvg} flex noOverflow onClick={this.toggleExpanded} title={`Click to ${this.state.isExpanded ? 'collapse' : 'expand'}.${header?.description ? ` ${header?.description}` : ''}`}>
|
||||
{hasCurrent ? <b>{header?.label}</b> : header?.label}
|
||||
</Button>
|
||||
<Button icon={Check} flex onClick={this.selectAll} style={{ flex: '0 0 50px', textAlign: 'right' }}>
|
||||
<Button icon={CheckSvg} flex onClick={this.selectAll} style={{ flex: '0 0 50px', textAlign: 'right' }}>
|
||||
All
|
||||
</Button>
|
||||
<Button icon={Close} flex onClick={this.selectNone} style={{ flex: '0 0 50px', textAlign: 'right' }}>
|
||||
<Button icon={CloseSvg} flex onClick={this.selectNone} style={{ flex: '0 0 50px', textAlign: 'right' }}>
|
||||
None
|
||||
</Button>
|
||||
</div>;
|
||||
@@ -245,7 +242,7 @@ class Section extends React.PureComponent<SectionProps, SectionState> {
|
||||
const { header, hasCurrent } = this.state;
|
||||
|
||||
return <div className='msp-control-group-header' style={{ marginTop: '1px' }}>
|
||||
<Button noOverflow icon={this.state.isExpanded ? ArrowDropDown : ArrowRight} onClick={this.toggleExpanded} title={`Click to ${this.state.isExpanded ? 'collapse' : 'expand'}. ${header?.description ? header?.description : ''}`}>
|
||||
<Button noOverflow icon={this.state.isExpanded ? ArrowDropDownSvg : ArrowRightSvg} onClick={this.toggleExpanded} title={`Click to ${this.state.isExpanded ? 'collapse' : 'expand'}. ${header?.description ? header?.description : ''}`}>
|
||||
{hasCurrent ? <b>{header?.label}</b> : header?.label}
|
||||
</Button>
|
||||
</div>;
|
||||
|
||||
@@ -6,11 +6,7 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import { Icon } from './icons';
|
||||
import ArrowRight from '@material-ui/icons/ArrowRight';
|
||||
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
|
||||
import Remove from '@material-ui/icons/Remove';
|
||||
import Add from '@material-ui/icons/Add';
|
||||
import { Icon, ArrowRightSvg, ArrowDropDownSvg, RemoveSvg, AddSvg } from './icons';
|
||||
|
||||
export type ColorAccent = 'cyan' | 'red' | 'gray' | 'green' | 'purple' | 'blue' | 'orange'
|
||||
|
||||
@@ -45,7 +41,7 @@ export class ControlGroup extends React.Component<{
|
||||
return <div className='msp-control-group-wrapper' style={{ position: 'relative', marginTop: this.props.noTopMargin ? 0 : void 0 }}>
|
||||
<div className='msp-control-group-header' style={{ marginLeft: this.props.headerLeftMargin }} title={this.props.title}>
|
||||
<Button onClick={this.headerClicked}>
|
||||
{!this.props.hideExpander && <Icon svg={this.state.isExpanded ? ArrowRight : ArrowDropDown} />}
|
||||
{!this.props.hideExpander && <Icon svg={this.state.isExpanded ? ArrowRightSvg : ArrowDropDownSvg} />}
|
||||
{this.props.topRightIcon && <Icon svg={this.props.topRightIcon} style={{ position: 'absolute', right: '2px', top: 0 }} />}
|
||||
<b>{this.props.header}</b>
|
||||
</Button>
|
||||
@@ -206,7 +202,7 @@ export class ExpandableControlRow extends React.Component<{
|
||||
{label}
|
||||
<button className='msp-btn-link msp-btn-icon msp-control-group-expander' onClick={this.toggleExpanded} title={`${this.state.isExpanded ? 'Less' : 'More'} options`}
|
||||
style={{ background: 'transparent', textAlign: 'left', padding: '0' }}>
|
||||
<Icon svg={this.state.isExpanded ? Remove : Add} style={{ display: 'inline-block' }} />
|
||||
<Icon svg={this.state.isExpanded ? RemoveSvg : AddSvg} style={{ display: 'inline-block' }} />
|
||||
</button>
|
||||
</>} control={pivot}>
|
||||
{this.props.colorStripe && <div className='msp-expandable-group-color-stripe' style={{ backgroundColor: Color.toStyle(this.props.colorStripe) }} />}
|
||||
@@ -347,7 +343,7 @@ export class ExpandGroup extends React.PureComponent<{ header: string, headerSty
|
||||
return <>
|
||||
<div className='msp-control-group-header' style={{ marginTop: this.props.marginTop !== void 0 ? this.props.marginTop : '1px', marginLeft: this.props.headerLeftMargin }}>
|
||||
<button className='msp-btn msp-form-control msp-btn-block' onClick={this.toggleExpanded} style={this.props.headerStyle}>
|
||||
<Icon svg={this.state.isExpanded ? ArrowDropDown : ArrowRight} />
|
||||
<Icon svg={this.state.isExpanded ? ArrowDropDownSvg : ArrowRightSvg} />
|
||||
{this.props.header}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -21,130 +21,421 @@ export function Icon(props: {
|
||||
|
||||
//
|
||||
|
||||
export function Union() { return _union; }
|
||||
export function Subtract() { return _subtract; }
|
||||
export function Intersect() { return _intersect; }
|
||||
export function SetSvg() { return _set; }
|
||||
export function MoleculeSvg() { return _molecule; }
|
||||
export function RulerSvg() { return _ruler; }
|
||||
export function CubeSvg() { return _cube; }
|
||||
|
||||
const circleLeft = <circle r="6px" id="circle-left" cy="12px" cx="8px" strokeWidth="1" />;
|
||||
const circleRight = <circle r="6px" id="circle-right" cy="12px" cx="16px" strokeWidth="1" />;
|
||||
|
||||
const _union = <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
{circleLeft}
|
||||
{circleRight}
|
||||
</defs>
|
||||
<g>
|
||||
<use href="#circle-left" className="msp-shape-filled" />
|
||||
<use href="#circle-right" className="msp-shape-filled" />
|
||||
<use href="#circle-left" className="msp-shape-empty" />
|
||||
</g>
|
||||
</svg>;
|
||||
export function UnionSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
{circleLeft}
|
||||
{circleRight}
|
||||
</defs>
|
||||
<g>
|
||||
<use href="#circle-left" className="msp-shape-filled" />
|
||||
<use href="#circle-right" className="msp-shape-filled" />
|
||||
<use href="#circle-left" className="msp-shape-empty" />
|
||||
</g>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
const _subtract = <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
{circleLeft}
|
||||
{circleRight}
|
||||
<mask id="mask-left">
|
||||
<use href="#circle-left" fill="white" stroke="white" />
|
||||
<use href="#circle-right" fill="black" strokeWidth="0" stroke="white" />
|
||||
</mask>
|
||||
</defs>
|
||||
<g>
|
||||
<use href="#circle-left" className="msp-shape-filled" mask="url(#mask-left)" />
|
||||
<use href="#circle-right" className="msp-shape-empty" />
|
||||
</g>
|
||||
</svg>;
|
||||
export function SubtractSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
{circleLeft}
|
||||
{circleRight}
|
||||
<mask id="mask-left">
|
||||
<use href="#circle-left" fill="white" stroke="white" />
|
||||
<use href="#circle-right" fill="black" strokeWidth="0" stroke="white" />
|
||||
</mask>
|
||||
</defs>
|
||||
<g>
|
||||
<use href="#circle-left" className="msp-shape-filled" mask="url(#mask-left)" />
|
||||
<use href="#circle-right" className="msp-shape-empty" />
|
||||
</g>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
const _intersect = <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
{circleLeft}
|
||||
{circleRight}
|
||||
<clipPath id="clip-left">
|
||||
<use href="#circle-right" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g>
|
||||
<use href="#circle-left" className="msp-shape-filled" clipPath="url(#clip-left)" />
|
||||
<use href="#circle-left" className="msp-shape-empty" />
|
||||
<use href="#circle-right" className="msp-shape-empty" />
|
||||
</g>
|
||||
</svg>;
|
||||
export function IntersectSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
{circleLeft}
|
||||
{circleRight}
|
||||
<clipPath id="clip-left">
|
||||
<use href="#circle-right" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g>
|
||||
<use href="#circle-left" className="msp-shape-filled" clipPath="url(#clip-left)" />
|
||||
<use href="#circle-left" className="msp-shape-empty" />
|
||||
<use href="#circle-right" className="msp-shape-empty" />
|
||||
</g>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
const _set = <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
{circleLeft}
|
||||
{circleRight}
|
||||
</defs>
|
||||
<g>
|
||||
<use href="#circle-left" className="msp-shape-empty" />
|
||||
<use href="#circle-right" className="msp-shape-filled" />
|
||||
</g>
|
||||
</svg>;
|
||||
export function SetSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<defs>
|
||||
{circleLeft}
|
||||
{circleRight}
|
||||
</defs>
|
||||
<g>
|
||||
<use href="#circle-left" className="msp-shape-empty" />
|
||||
<use href="#circle-right" className="msp-shape-filled" />
|
||||
</g>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
const _molecule = <svg width="17px" height="17px" viewBox="0 0 299.463 299.463">
|
||||
<g>
|
||||
<path d="M256.851,173.832v-48.201c22.916-4.918,34.151-30.668,22.556-50.771c-11.547-20.004-39.486-23.251-55.242-5.844
|
||||
l-41.746-24.106C189.618,22.603,172.861,0,149.734,0c-23.132,0-39.881,22.609-32.685,44.911L75.305,69.016
|
||||
C59.522,51.586,31.597,54.88,20.061,74.863c-11.63,20.163-0.298,45.862,22.557,50.769v48.2
|
||||
c-22.821,4.898-34.195,30.591-22.556,50.771c11.529,19.972,39.454,23.285,55.242,5.845l41.746,24.106
|
||||
c-7.199,22.308,9.559,44.911,32.685,44.911c23.132,0,39.88-22.609,32.685-44.911l41.745-24.106
|
||||
c15.817,17.469,43.73,14.099,55.242-5.844c0,0,0-0.001,0.001-0.002c4.587-7.953,5.805-17.213,3.431-26.076
|
||||
C279.392,185.657,269.129,176.461,256.851,173.832z M249.62,72.088c20.568,0,27.428,27.191,10.008,37.239
|
||||
c-0.003,0.002-0.006,0.003-0.009,0.005c-10.04,5.81-22.85,1.762-27.877-8.475C225.206,87.548,234.938,72.088,249.62,72.088z
|
||||
M149.734,14.4c11.005,0,19.958,8.954,19.958,19.959c0,11.127-9.077,19.958-19.958,19.958c-10.95,0-19.958-8.9-19.958-19.958
|
||||
C129.776,23.354,138.729,14.4,149.734,14.4z M39.84,109.328c-17.451-10.067-10.534-37.24,10.01-37.24
|
||||
c15.311,0,24.922,16.653,17.251,29.942C61.681,111.397,49.517,114.925,39.84,109.328z M59.802,224.702
|
||||
c-9.535,5.503-21.768,2.229-27.268-7.298c-7.639-13.242,1.887-29.945,17.236-29.945c0.013,0,0.027,0,0.04,0
|
||||
C70.07,187.48,77.49,214.469,59.802,224.702z M149.734,285.062c-11.005,0-19.958-8.954-19.958-19.958
|
||||
c0-11.127,9.077-19.958,19.958-19.958c10.954,0,19.958,8.903,19.958,19.958C169.693,276.109,160.74,285.062,149.734,285.062z
|
||||
M216.953,217.982l-41.727,24.095c-13.778-15.22-37.459-14.94-50.983,0l-41.728-24.096c6.196-19.289-5.541-39.835-25.498-44.149
|
||||
V125.63c19.752-4.268,31.762-24.65,25.498-44.149l41.727-24.095c13.629,15.055,37.32,15.093,50.983,0l41.728,24.096
|
||||
c-6.196,19.29,5.534,39.835,25.498,44.149v48.202C222.61,178.123,210.721,198.581,216.953,217.982z M266.935,217.404
|
||||
c-5.501,9.528-17.732,12.802-27.261,7.302c-17.682-10.23-10.301-37.247,10.032-37.247
|
||||
C264.984,187.459,274.602,204.112,266.935,217.404z"/>
|
||||
</g>
|
||||
</svg>;
|
||||
export function MoleculeSvg() {
|
||||
return <svg width="17px" height="17px" viewBox="0 0 299.463 299.463">
|
||||
<g>
|
||||
<path d="M256.851,173.832v-48.201c22.916-4.918,34.151-30.668,22.556-50.771c-11.547-20.004-39.486-23.251-55.242-5.844 l-41.746-24.106C189.618,22.603,172.861,0,149.734,0c-23.132,0-39.881,22.609-32.685,44.911L75.305,69.016 C59.522,51.586,31.597,54.88,20.061,74.863c-11.63,20.163-0.298,45.862,22.557,50.769v48.2 c-22.821,4.898-34.195,30.591-22.556,50.771c11.529,19.972,39.454,23.285,55.242,5.845l41.746,24.106 c-7.199,22.308,9.559,44.911,32.685,44.911c23.132,0,39.88-22.609,32.685-44.911l41.745-24.106 c15.817,17.469,43.73,14.099,55.242-5.844c0,0,0-0.001,0.001-0.002c4.587-7.953,5.805-17.213,3.431-26.076 C279.392,185.657,269.129,176.461,256.851,173.832z M249.62,72.088c20.568,0,27.428,27.191,10.008,37.239 c-0.003,0.002-0.006,0.003-0.009,0.005c-10.04,5.81-22.85,1.762-27.877-8.475C225.206,87.548,234.938,72.088,249.62,72.088z M149.734,14.4c11.005,0,19.958,8.954,19.958,19.959c0,11.127-9.077,19.958-19.958,19.958c-10.95,0-19.958-8.9-19.958-19.958 C129.776,23.354,138.729,14.4,149.734,14.4z M39.84,109.328c-17.451-10.067-10.534-37.24,10.01-37.24 c15.311,0,24.922,16.653,17.251,29.942C61.681,111.397,49.517,114.925,39.84,109.328z M59.802,224.702 c-9.535,5.503-21.768,2.229-27.268-7.298c-7.639-13.242,1.887-29.945,17.236-29.945c0.013,0,0.027,0,0.04,0 C70.07,187.48,77.49,214.469,59.802,224.702z M149.734,285.062c-11.005,0-19.958-8.954-19.958-19.958 c0-11.127,9.077-19.958,19.958-19.958c10.954,0,19.958,8.903,19.958,19.958C169.693,276.109,160.74,285.062,149.734,285.062z M216.953,217.982l-41.727,24.095c-13.778-15.22-37.459-14.94-50.983,0l-41.728-24.096c6.196-19.289-5.541-39.835-25.498-44.149 V125.63c19.752-4.268,31.762-24.65,25.498-44.149l41.727-24.095c13.629,15.055,37.32,15.093,50.983,0l41.728,24.096 c-6.196,19.29,5.534,39.835,25.498,44.149v48.202C222.61,178.123,210.721,198.581,216.953,217.982z M266.935,217.404 c-5.501,9.528-17.732,12.802-27.261,7.302c-17.682-10.23-10.301-37.247,10.032-37.247 C264.984,187.459,274.602,204.112,266.935,217.404z"/>
|
||||
</g>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
const _ruler = <svg viewBox="0 0 508.073 508.073" width="17px" height="17px">
|
||||
<g>
|
||||
<path d="M470.459,378.925c-0.7-2.1-1.9-4-3.4-5.5l-113.9-113.9l149.8-149.8c10-10,2.6-17.3,0-19.9l-85.7-85.7
|
||||
c-5.5-5.5-14.4-5.5-19.9,0l-149.8,149.8l-134.7-134.7c-25.5-25.5-67.8-25.6-93.4,0c-25.8,25.8-25.8,67.7,0,93.5l134.6,134.7
|
||||
l-149.9,149.9c-5.5,5.5-5.5,14.4,0,19.9l85.6,85.7c2.6,2.6,10,10,19.9,0l150-149.9l113.9,113.9c1.5,1.5,3.4,2.7,5.5,3.4
|
||||
l110.4,36.9c6,2,10.7,0.3,14.4-3.4c3.8-3.8,5.1-9.4,3.4-14.4L470.459,378.925z M276.159,165.225l29.9,29.9
|
||||
c5.5,5.5,14.4,5.5,19.9,0c5-5,5.5-14.4,0-19.9l-29.9-29.9l23.7-23.7l13,13c5.5,5.5,14.4,5.5,19.9,0c5.2-5.2,6.2-13.7,0-19.9
|
||||
l-13-13l23.7-23.7l29.4,29.4c5.5,5.5,14.4,5.5,19.9,0c5.6-5.6,5.5-14.4,0-19.9l-29.4-29.5l24-24l65.8,65.7l-139.8,139.9
|
||||
l-65.8-65.8L276.159,165.225z M39.359,92.825c-14.8-14.8-14.8-38.8,0-53.6c14.1-14.1,38.8-14.7,53.6,0l15.5,15.5l-53.6,53.6
|
||||
L39.359,92.825z M99.759,473.025l-65.7-65.7l24-24l13.2,13.2c5.5,5.5,14.4,5.6,19.9,0c5.5-5.5,5.5-14.4,0-19.9l-13.1-13.3
|
||||
l23.7-23.7l29.6,29.6c6.2,6.2,14.7,5.2,19.9,0c5.5-5.5,5.5-14.4,0-19.9l-29.6-29.6l23.7-23.7l13.2,13.2c5.5,5.5,14.9,5,19.9,0
|
||||
c5.5-5.5,5.5-14.4,0-19.9l-13.2-13.2l8.8-8.8l65.8,65.7L99.759,473.025z M74.759,128.225l53.6-53.6l308.7,308.7l-53.6,53.6
|
||||
L74.759,128.225z M409.659,450.725l41.3-41.3l20.7,61.9L409.659,450.725z"/>
|
||||
</g>
|
||||
</svg>;
|
||||
export function RulerSvg() {
|
||||
return <svg viewBox="0 0 508.073 508.073" width="17px" height="17px">
|
||||
<g>
|
||||
<path d="M470.459,378.925c-0.7-2.1-1.9-4-3.4-5.5l-113.9-113.9l149.8-149.8c10-10,2.6-17.3,0-19.9l-85.7-85.7 c-5.5-5.5-14.4-5.5-19.9,0l-149.8,149.8l-134.7-134.7c-25.5-25.5-67.8-25.6-93.4,0c-25.8,25.8-25.8,67.7,0,93.5l134.6,134.7 l-149.9,149.9c-5.5,5.5-5.5,14.4,0,19.9l85.6,85.7c2.6,2.6,10,10,19.9,0l150-149.9l113.9,113.9c1.5,1.5,3.4,2.7,5.5,3.4 l110.4,36.9c6,2,10.7,0.3,14.4-3.4c3.8-3.8,5.1-9.4,3.4-14.4L470.459,378.925z M276.159,165.225l29.9,29.9 c5.5,5.5,14.4,5.5,19.9,0c5-5,5.5-14.4,0-19.9l-29.9-29.9l23.7-23.7l13,13c5.5,5.5,14.4,5.5,19.9,0c5.2-5.2,6.2-13.7,0-19.9 l-13-13l23.7-23.7l29.4,29.4c5.5,5.5,14.4,5.5,19.9,0c5.6-5.6,5.5-14.4,0-19.9l-29.4-29.5l24-24l65.8,65.7l-139.8,139.9 l-65.8-65.8L276.159,165.225z M39.359,92.825c-14.8-14.8-14.8-38.8,0-53.6c14.1-14.1,38.8-14.7,53.6,0l15.5,15.5l-53.6,53.6 L39.359,92.825z M99.759,473.025l-65.7-65.7l24-24l13.2,13.2c5.5,5.5,14.4,5.6,19.9,0c5.5-5.5,5.5-14.4,0-19.9l-13.1-13.3 l23.7-23.7l29.6,29.6c6.2,6.2,14.7,5.2,19.9,0c5.5-5.5,5.5-14.4,0-19.9l-29.6-29.6l23.7-23.7l13.2,13.2c5.5,5.5,14.9,5,19.9,0 c5.5-5.5,5.5-14.4,0-19.9l-13.2-13.2l8.8-8.8l65.8,65.7L99.759,473.025z M74.759,128.225l53.6-53.6l308.7,308.7l-53.6,53.6 L74.759,128.225z M409.659,450.725l41.3-41.3l20.7,61.9L409.659,450.725z"/>
|
||||
</g>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
const _cube = <svg viewBox="0 0 270.06 270.06" width="17px" height="17px">
|
||||
<g>
|
||||
<path d="M264.898,0.007
|
||||
c-0.181,0.006-0.362,0.023-0.541,0.049H84.996c-1.326,0-2.598,0.527-3.535,1.465l-80,80C0.525,82.459-0.001,83.73,0,85.056v180
|
||||
c0,2.761,2.239,5,5,5h180c1.326,0,2.598-0.527,3.535-1.465l80-80c0.938-0.938,1.465-2.209,1.465-3.535V5.819
|
||||
c0.14-0.893,0.035-1.807-0.303-2.645c-0.016-0.045-0.033-0.09-0.051-0.135c-0.808-1.89-2.69-3.093-4.744-3.033L264.898,0.007z
|
||||
M87.066,10.056h165.859l-70,70H17.066L87.066,10.056z M259.996,17.126v165.859l-70,70V87.126L259.996,17.126L259.996,17.126z
|
||||
M84.92,19.985c-2.759,0.042-4.963,2.311-4.924,5.07v40c-0.039,2.761,2.168,5.032,4.929,5.071s5.032-2.168,5.071-4.929
|
||||
c0.001-0.047,0.001-0.094,0-0.141v-40c0.039-2.761-2.168-5.031-4.93-5.07C85.018,19.984,84.969,19.984,84.92,19.985z M9.996,90.056
|
||||
h170v170h-170V90.056L9.996,90.056z M84.92,99.985c-2.759,0.042-4.963,2.311-4.924,5.07v30c-0.039,2.761,2.168,5.032,4.929,5.071
|
||||
s5.032-2.168,5.071-4.929c0.001-0.047,0.001-0.094,0-0.141v-30c0.039-2.761-2.168-5.031-4.93-5.07
|
||||
C85.018,99.984,84.969,99.984,84.92,99.985z M84.92,159.985c-2.759,0.042-4.963,2.311-4.924,5.07v17.93L61.461,201.52
|
||||
c-1.992,1.913-2.057,5.078-0.144,7.07c1.913,1.992,5.078,2.057,7.07,0.144c0.049-0.047,0.097-0.095,0.144-0.144l18.535-18.535h17.93
|
||||
c2.761,0.039,5.032-2.168,5.071-4.929s-2.168-5.032-4.929-5.071c-0.047-0.001-0.094-0.001-0.141,0h-15v-15
|
||||
c0.039-2.761-2.168-5.031-4.93-5.07C85.018,159.984,84.969,159.984,84.92,159.985z M134.996,180.055
|
||||
c-2.761-0.039-5.032,2.168-5.071,4.929c-0.039,2.761,2.168,5.032,4.929,5.071c0.047,0.001,0.094,0.001,0.141,0h30
|
||||
c2.761,0.039,5.032-2.168,5.071-4.929c0.039-2.761-2.168-5.032-4.929-5.071c-0.047-0.001-0.094-0.001-0.141,0H134.996z
|
||||
M204.996,180.055c-2.761-0.039-5.032,2.168-5.071,4.929c-0.039,2.761,2.168,5.032,4.929,5.071c0.047,0.001,0.094,0.001,0.141,0h40
|
||||
c2.761,0.039,5.032-2.168,5.071-4.929s-2.168-5.032-4.929-5.071c-0.047-0.001-0.094-0.001-0.141,0H204.996z M44.898,220.007
|
||||
c-1.299,0.039-2.532,0.582-3.438,1.514l-20,20c-1.992,1.913-2.057,5.078-0.144,7.07c1.913,1.992,5.078,2.057,7.07,0.144
|
||||
c0.049-0.047,0.097-0.095,0.144-0.144l20-20c1.98-1.925,2.025-5.091,0.1-7.071C47.654,220.514,46.3,219.965,44.898,220.007z"/>
|
||||
</g>
|
||||
</svg>;
|
||||
export function CubeSvg() {
|
||||
return <svg viewBox="0 0 270.06 270.06" width="17px" height="17px">
|
||||
<g>
|
||||
<path d="M264.898,0.007 c-0.181,0.006-0.362,0.023-0.541,0.049H84.996c-1.326,0-2.598,0.527-3.535,1.465l-80,80C0.525,82.459-0.001,83.73,0,85.056v180 c0,2.761,2.239,5,5,5h180c1.326,0,2.598-0.527,3.535-1.465l80-80c0.938-0.938,1.465-2.209,1.465-3.535V5.819 c0.14-0.893,0.035-1.807-0.303-2.645c-0.016-0.045-0.033-0.09-0.051-0.135c-0.808-1.89-2.69-3.093-4.744-3.033L264.898,0.007z M87.066,10.056h165.859l-70,70H17.066L87.066,10.056z M259.996,17.126v165.859l-70,70V87.126L259.996,17.126L259.996,17.126z M84.92,19.985c-2.759,0.042-4.963,2.311-4.924,5.07v40c-0.039,2.761,2.168,5.032,4.929,5.071s5.032-2.168,5.071-4.929 c0.001-0.047,0.001-0.094,0-0.141v-40c0.039-2.761-2.168-5.031-4.93-5.07C85.018,19.984,84.969,19.984,84.92,19.985z M9.996,90.056 h170v170h-170V90.056L9.996,90.056z M84.92,99.985c-2.759,0.042-4.963,2.311-4.924,5.07v30c-0.039,2.761,2.168,5.032,4.929,5.071 s5.032-2.168,5.071-4.929c0.001-0.047,0.001-0.094,0-0.141v-30c0.039-2.761-2.168-5.031-4.93-5.07 C85.018,99.984,84.969,99.984,84.92,99.985z M84.92,159.985c-2.759,0.042-4.963,2.311-4.924,5.07v17.93L61.461,201.52 c-1.992,1.913-2.057,5.078-0.144,7.07c1.913,1.992,5.078,2.057,7.07,0.144c0.049-0.047,0.097-0.095,0.144-0.144l18.535-18.535h17.93 c2.761,0.039,5.032-2.168,5.071-4.929s-2.168-5.032-4.929-5.071c-0.047-0.001-0.094-0.001-0.141,0h-15v-15 c0.039-2.761-2.168-5.031-4.93-5.07C85.018,159.984,84.969,159.984,84.92,159.985z M134.996,180.055 c-2.761-0.039-5.032,2.168-5.071,4.929c-0.039,2.761,2.168,5.032,4.929,5.071c0.047,0.001,0.094,0.001,0.141,0h30 c2.761,0.039,5.032-2.168,5.071-4.929c0.039-2.761-2.168-5.032-4.929-5.071c-0.047-0.001-0.094-0.001-0.141,0H134.996z M204.996,180.055c-2.761-0.039-5.032,2.168-5.071,4.929c-0.039,2.761,2.168,5.032,4.929,5.071c0.047,0.001,0.094,0.001,0.141,0h40 c2.761,0.039,5.032-2.168,5.071-4.929s-2.168-5.032-4.929-5.071c-0.047-0.001-0.094-0.001-0.141,0H204.996z M44.898,220.007 c-1.299,0.039-2.532,0.582-3.438,1.514l-20,20c-1.992,1.913-2.057,5.078-0.144,7.07c1.913,1.992,5.078,2.057,7.07,0.144 c0.049-0.047,0.097-0.095,0.144-0.144l20-20c1.98-1.925,2.025-5.091,0.1-7.071C47.654,220.514,46.3,219.965,44.898,220.007z"/>
|
||||
</g>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
// The following icons are adapted from https://materialdesignicons.com/ and
|
||||
// licensed with https://github.com/Templarian/MaterialDesign/blob/master/LICENSE
|
||||
|
||||
export function CursorDefaultOutlineSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M10.07,14.27C10.57,14.03 11.16,14.25 11.4,14.75L13.7,19.74L15.5,18.89L13.19,13.91C12.95,13.41 13.17,12.81 13.67,12.58L13.95,12.5L16.25,12.05L8,5.12V15.9L9.82,14.43L10.07,14.27M13.64,21.97C13.14,22.21 12.54,22 12.31,21.5L10.13,16.76L7.62,18.78C7.45,18.92 7.24,19 7,19A1,1 0 0,1 6,18V3A1,1 0 0,1 7,2C7.24,2 7.47,2.09 7.64,2.23L7.65,2.22L19.14,11.86C19.57,12.22 19.62,12.85 19.27,13.27C19.12,13.45 18.91,13.57 18.7,13.61L15.54,14.23L17.74,18.96C18,19.46 17.76,20.05 17.26,20.28L13.64,21.97Z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function FileOutlineSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24" strokeWidth="0.1">
|
||||
<path fill="currentColor" d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
// The following icons are adapted from https://material-ui.com/components/material-icons/ and
|
||||
// licensed with https://github.com/mui-org/material-ui/blob/master/LICENSE
|
||||
|
||||
export function AccountTreeOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M22 11V3h-7v3H9V3H2v8h7V8h2v10h4v3h7v-8h-7v3h-2V8h2v3h7zM7 9H4V5h3v4zm10 6h3v4h-3v-4zm0-10h3v4h-3V5z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function AddSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function ArrowDownwardSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function ArrowDropDownSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M7 10l5 5 5-5z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function ArrowRightSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M10 17l5-5-5-5v10z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function ArrowUpwardSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function AutorenewSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function BlurOnSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M6 13c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-8c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm-3 .5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM6 5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm15 5.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM14 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-3.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm-11 10c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm7 7c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm0-17c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM10 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0 5.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm8 .5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-8c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm3 8.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM14 17c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm-4-12c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0 8.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm4-4.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-4c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function BookmarksOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M15 7v12.97l-4.21-1.81-.79-.34-.79.34L5 19.97V7h10m4-6H8.99C7.89 1 7 1.9 7 3h10c1.1 0 2 .9 2 2v13l2 1V3c0-1.1-.9-2-2-2zm-4 4H5c-1.1 0-2 .9-2 2v16l7-3 7 3V7c0-1.1-.9-2-2-2z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function BrushSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M7 14c-1.66 0-3 1.34-3 3 0 1.31-1.16 2-2 2 .92 1.22 2.49 2 4 2 2.21 0 4-1.79 4-4 0-1.66-1.34-3-3-3zm13.71-9.37l-1.34-1.34a.9959.9959 0 00-1.41 0L9 12.25 11.75 15l8.96-8.96c.39-.39.39-1.02 0-1.41z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function BuildOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M22.61 18.99l-9.08-9.08c.93-2.34.45-5.1-1.44-7C9.79.61 6.21.4 3.66 2.26L7.5 6.11 6.08 7.52 2.25 3.69C.39 6.23.6 9.82 2.9 12.11c1.86 1.86 4.57 2.35 6.89 1.48l9.11 9.11c.39.39 1.02.39 1.41 0l2.3-2.3c.4-.38.4-1.01 0-1.41zm-3 1.6l-9.46-9.46c-.61.45-1.29.72-2 .82-1.36.2-2.79-.21-3.83-1.25C3.37 9.76 2.93 8.5 3 7.26l3.09 3.09 4.24-4.24-3.09-3.09c1.24-.07 2.49.37 3.44 1.31 1.08 1.08 1.49 2.57 1.24 3.96-.12.71-.42 1.37-.88 1.96l9.45 9.45-.88.89z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function BuildSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CameraOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M14.25 2.26l-.08-.04-.01.02C13.46 2.09 12.74 2 12 2 6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10c0-4.75-3.31-8.72-7.75-9.74zM19.41 9h-7.99l2.71-4.7c2.4.66 4.35 2.42 5.28 4.7zM13.1 4.08L10.27 9l-1.15 2L6.4 6.3C7.84 4.88 9.82 4 12 4c.37 0 .74.03 1.1.08zM5.7 7.09L8.54 12l1.15 2H4.26C4.1 13.36 4 12.69 4 12c0-1.85.64-3.55 1.7-4.91zM4.59 15h7.98l-2.71 4.7c-2.4-.67-4.34-2.42-5.27-4.7zm6.31 4.91L14.89 13l2.72 4.7C16.16 19.12 14.18 20 12 20c-.38 0-.74-.04-1.1-.09zm7.4-3l-4-6.91h5.43c.17.64.27 1.31.27 2 0 1.85-.64 3.55-1.7 4.91z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CameraSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M9.4 10.5l4.77-8.26C13.47 2.09 12.75 2 12 2c-2.4 0-4.6.85-6.32 2.25l3.66 6.35.06-.1zM21.54 9c-.92-2.92-3.15-5.26-6-6.34L11.88 9h9.66zm.26 1h-7.49l.29.5 4.76 8.25C21 16.97 22 14.61 22 12c0-.69-.07-1.35-.2-2zM8.54 12l-3.9-6.75C3.01 7.03 2 9.39 2 12c0 .69.07 1.35.2 2h7.49l-1.15-2zm-6.08 3c.92 2.92 3.15 5.26 6 6.34L12.12 15H2.46zm11.27 0l-3.9 6.76c.7.15 1.42.24 2.17.24 2.4 0 4.6-.85 6.32-2.25l-3.66-6.35-.93 1.6z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CancelOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.59-13L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CancelSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CenterFocusStrongSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm-7 7H3v4c0 1.1.9 2 2 2h4v-2H5v-4zM5 5h4V3H5c-1.1 0-2 .9-2 2v4h2V5zm14-2h-4v2h4v4h2V5c0-1.1-.9-2-2-2zm0 16h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CheckSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function ClearSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CloseSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CloudUploadSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function CodeSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function DeleteOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function DeleteSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function ErrorSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function ExtensionSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function FlipToFrontSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24" strokeWidth="0.1px">
|
||||
<path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3c0 1.1.89 2 2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9c-1.11 0-2 .9-2 2v10c0 1.1.89 2 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function FullscreenSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function GetAppSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function HelpOutlineSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function HomeOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M12 5.69l5 4.5V18h-2v-6H9v6H7v-7.81l5-4.5M12 3L2 12h3v8h6v-6h2v6h6v-8h3L12 3z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function LaunchSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function LinearScaleSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19.5 9.5c-1.03 0-1.9.62-2.29 1.5h-2.92c-.39-.88-1.26-1.5-2.29-1.5s-1.9.62-2.29 1.5H6.79c-.39-.88-1.26-1.5-2.29-1.5C3.12 9.5 2 10.62 2 12s1.12 2.5 2.5 2.5c1.03 0 1.9-.62 2.29-1.5h2.92c.39.88 1.26 1.5 2.29 1.5s1.9-.62 2.29-1.5h2.92c.39.88 1.26 1.5 2.29 1.5 1.38 0 2.5-1.12 2.5-2.5s-1.12-2.5-2.5-2.5z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function MoreHorizSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function NavigateBeforeSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function NavigateNextSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function OpenInBrowserSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function PlayArrowSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M8 5v14l11-7z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function RefreshSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function RemoveSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M19 13H5v-2h14v2z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function RestoreSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function SaveOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm2 16H5V5h11.17L19 7.83V19zm-7-7c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zM6 6h9v4H6z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function ScatterPlotSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<circle cx="7" cy="14" r="3" /><circle cx="11" cy="6" r="3" /><circle cx="16.6" cy="17.6" r="3" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function SkipPreviousSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M6 6h2v12H6zm3.5 6l8.5 6V6z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function StopSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M6 6h12v12H6z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function SubscriptionsOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M4 6h16v2H4zm2-4h12v2H6zm14 8H4c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2v-8c0-1.1-.9-2-2-2zm0 10H4v-8h16v8zm-10-7.27v6.53L16 16z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function SwapHorizSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function TuneSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function VisibilityOffOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M12 6c3.79 0 7.17 2.13 8.82 5.5-.59 1.22-1.42 2.27-2.41 3.12l1.41 1.41c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 0-2.49.2-3.64.57l1.65 1.65C10.66 6.09 11.32 6 12 6zm-1.07 1.14L13 9.21c.57.25 1.03.71 1.28 1.28l2.07 2.07c.08-.34.14-.7.14-1.07C16.5 9.01 14.48 7 12 7c-.37 0-.72.05-1.07.14zM2.01 3.87l2.68 2.68C3.06 7.83 1.77 9.53 1 11.5 2.73 15.89 7 19 12 19c1.52 0 2.98-.29 4.32-.82l3.42 3.42 1.41-1.41L3.42 2.45 2.01 3.87zm7.5 7.5l2.61 2.61c-.04.01-.08.02-.12.02-1.38 0-2.5-1.12-2.5-2.5 0-.05.01-.08.01-.13zm-3.4-3.4l1.75 1.75c-.23.55-.36 1.15-.36 1.78 0 2.48 2.02 4.5 4.5 4.5.63 0 1.23-.13 1.77-.36l.98.98c-.88.24-1.8.38-2.75.38-3.79 0-7.17-2.13-8.82-5.5.7-1.43 1.72-2.61 2.93-3.53z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function VisibilityOutlinedSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M12 6c3.79 0 7.17 2.13 8.82 5.5C19.17 14.87 15.79 17 12 17s-7.17-2.13-8.82-5.5C4.83 8.13 8.21 6 12 6m0-2C7 4 2.73 7.11 1 11.5 2.73 15.89 7 19 12 19s9.27-3.11 11-7.5C21.27 7.11 17 4 12 4zm0 5c1.38 0 2.5 1.12 2.5 2.5S13.38 14 12 14s-2.5-1.12-2.5-2.5S10.62 9 12 9m0-2c-2.48 0-4.5 2.02-4.5 4.5S9.52 16 12 16s4.5-2.02 4.5-4.5S14.48 7 12 7z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
export function WarningSvg() {
|
||||
return <svg width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" />
|
||||
</svg>;
|
||||
}
|
||||
|
||||
// Aliases
|
||||
|
||||
export const SelectionModeSvg = CursorDefaultOutlineSvg;
|
||||
export const SuperposeAtomsSvg = ScatterPlotSvg;
|
||||
export const SuperposeChainsSvg = LinearScaleSvg;
|
||||
export const SuperpositionSvg = FlipToFrontSvg;
|
||||
|
||||
@@ -5,16 +5,6 @@
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import ArrowDownward from '@material-ui/icons/ArrowDownward';
|
||||
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
|
||||
import ArrowRight from '@material-ui/icons/ArrowRight';
|
||||
import ArrowUpward from '@material-ui/icons/ArrowUpward';
|
||||
import BookmarksOutlined from '@material-ui/icons/BookmarksOutlined';
|
||||
import Check from '@material-ui/icons/Check';
|
||||
import Clear from '@material-ui/icons/Clear';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import HelpOutline from '@material-ui/icons/HelpOutline';
|
||||
import MoreHoriz from '@material-ui/icons/MoreHoriz';
|
||||
import * as React from 'react';
|
||||
import { Mat4, Vec2, Vec3 } from '../../mol-math/linear-algebra';
|
||||
import { PluginContext } from '../../mol-plugin/context';
|
||||
@@ -30,7 +20,7 @@ import { PluginUIComponent } from '../base';
|
||||
import { ActionMenu } from './action-menu';
|
||||
import { ColorOptions, ColorValueOption, CombinedColorControl } from './color';
|
||||
import { Button, ControlGroup, ControlRow, ExpandGroup, IconButton, TextInput, ToggleButton } from './common';
|
||||
import { Icon } from './icons';
|
||||
import { Icon, HelpOutlineSvg, CheckSvg, ClearSvg, BookmarksOutlinedSvg, MoreHorizSvg, ArrowDropDownSvg, ArrowRightSvg, ArrowDownwardSvg, ArrowUpwardSvg, DeleteOutlinedSvg } from './icons';
|
||||
import { legendFor } from './legend';
|
||||
import LineGraphComponent from './line-graph/line-graph-component';
|
||||
import { Slider, Slider2 } from './slider';
|
||||
@@ -216,7 +206,7 @@ export class ParamHelp<L extends LegendData> extends React.PureComponent<{ legen
|
||||
|
||||
return <div className='msp-help-text'>
|
||||
<div>
|
||||
<div className='msp-help-description'><Icon svg={HelpOutline} inline />{description}</div>
|
||||
<div className='msp-help-description'><Icon svg={HelpOutlineSvg} inline />{description}</div>
|
||||
{Legend && <div className='msp-help-legend'><Legend legend={legend} /></div>}
|
||||
</div>
|
||||
</div>;
|
||||
@@ -259,8 +249,7 @@ function renderSimple(options: { props: ParamProps<any>, state: { showHelp: bool
|
||||
<button className='msp-help msp-btn-link msp-btn-icon msp-control-group-expander' onClick={toggleHelp}
|
||||
title={desc || `${state.showHelp ? 'Hide' : 'Show'} help`}
|
||||
style={{ background: 'transparent', textAlign: 'left', padding: '0' }}>
|
||||
{/* TODO: <Icon name={state.showHelp ? 'help-circle-collapse' : 'help-circle-expand'} /> */}
|
||||
<Icon svg={HelpOutline} />
|
||||
<Icon svg={HelpOutlineSvg} />
|
||||
</button>
|
||||
}
|
||||
</>}
|
||||
@@ -300,7 +289,7 @@ export class BoolControl extends SimpleParam<PD.BooleanParam> {
|
||||
onClick = (e: React.MouseEvent<HTMLButtonElement>) => { this.update(!this.props.value); e.currentTarget.blur(); }
|
||||
renderControl() {
|
||||
return <button onClick={this.onClick} disabled={this.props.isDisabled}>
|
||||
<Icon svg={this.props.value ? Check : Clear} />
|
||||
<Icon svg={this.props.value ? CheckSvg : ClearSvg} />
|
||||
{this.props.value ? 'On' : 'Off'}
|
||||
</button>;
|
||||
}
|
||||
@@ -466,8 +455,8 @@ export class SelectControl extends React.PureComponent<ParamProps<PD.Select<stri
|
||||
const toggle = this.props.param.cycle ? this.cycle : this.toggle;
|
||||
const textAlign = this.props.param.cycle ? 'center' : 'left';
|
||||
const icon = this.props.param.cycle
|
||||
? (this.props.value === 'on' ? Check
|
||||
: this.props.value === 'off' ? Clear : void 0)
|
||||
? (this.props.value === 'on' ? CheckSvg
|
||||
: this.props.value === 'off' ? ClearSvg : void 0)
|
||||
: void 0;
|
||||
|
||||
return <ToggleButton disabled={this.props.isDisabled} style={{ textAlign, overflow: 'hidden', textOverflow: 'ellipsis' }}
|
||||
@@ -644,7 +633,7 @@ export class ColorListControl extends React.PureComponent<ParamProps<PD.ColorLis
|
||||
{value.colors.length === 1 ? '1 color' : `${value.colors.length} colors`}
|
||||
<div style={colorStripStyle(value, '33px')} />
|
||||
</button>
|
||||
<IconButton svg={BookmarksOutlined} onClick={this.togglePresets} toggleState={this.state.show === 'presets'} title='Color Presets'
|
||||
<IconButton svg={BookmarksOutlinedSvg} onClick={this.togglePresets} toggleState={this.state.show === 'presets'} title='Color Presets'
|
||||
style={{ padding: 0, position: 'absolute', right: 0, top: 0, width: '32px' }} />
|
||||
</>;
|
||||
}
|
||||
@@ -939,7 +928,7 @@ export class GroupControl extends React.PureComponent<ParamProps<PD.Group<any>>
|
||||
if (!this.state.isExpanded) {
|
||||
return <div className='msp-mapped-parameter-group'>
|
||||
{ctrl}
|
||||
<IconButton svg={MoreHoriz} onClick={this.toggleExpanded} toggleState={this.state.isExpanded} title={`More Options`} />
|
||||
<IconButton svg={MoreHorizSvg} onClick={this.toggleExpanded} toggleState={this.state.isExpanded} title={`More Options`} />
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -950,7 +939,7 @@ export class GroupControl extends React.PureComponent<ParamProps<PD.Group<any>>
|
||||
|
||||
return <div className='msp-mapped-parameter-group'>
|
||||
{ctrl}
|
||||
<IconButton svg={MoreHoriz} onClick={this.toggleExpanded} toggleState={this.state.isExpanded} title={`More Options`} />
|
||||
<IconButton svg={MoreHorizSvg} onClick={this.toggleExpanded} toggleState={this.state.isExpanded} title={`More Options`} />
|
||||
<div className='msp-control-offset'>
|
||||
<ParameterControls params={filtered} onEnter={this.props.onEnter} values={this.props.value} onChange={this.onChangeParam} isDisabled={this.props.isDisabled} />
|
||||
</div>
|
||||
@@ -980,7 +969,7 @@ export class GroupControl extends React.PureComponent<ParamProps<PD.Group<any>>
|
||||
return <div className='msp-control-group-wrapper'>
|
||||
<div className='msp-control-group-header'>
|
||||
<button className='msp-btn msp-form-control msp-btn-block' onClick={this.toggleExpanded}>
|
||||
<Icon svg={this.state.isExpanded ? ArrowDropDown : ArrowRight} />
|
||||
<Icon svg={this.state.isExpanded ? ArrowDropDownSvg : ArrowRightSvg} />
|
||||
{label}
|
||||
</button>
|
||||
</div>
|
||||
@@ -1056,7 +1045,7 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any>
|
||||
if (!this.areParamsEmpty(param.params)) {
|
||||
return <div className='msp-mapped-parameter-group'>
|
||||
{Select}
|
||||
<IconButton svg={MoreHoriz} onClick={this.toggleExpanded} toggleState={this.state.isExpanded} title={`${label} Properties`} />
|
||||
<IconButton svg={MoreHorizSvg} onClick={this.toggleExpanded} toggleState={this.state.isExpanded} title={`${label} Properties`} />
|
||||
{this.state.isExpanded && <GroupControl inMapped param={param} value={value.params} name={value.name} onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} />}
|
||||
</div>;
|
||||
}
|
||||
@@ -1134,9 +1123,9 @@ class ObjectListItem extends React.PureComponent<ObjectListItemProps, { isExpand
|
||||
{this.props.param.getLabel(this.props.value)}
|
||||
</button>
|
||||
<div>
|
||||
<IconButton svg={ArrowDownward} title='Move Up' onClick={this.moveUp} small={true} />
|
||||
<IconButton svg={ArrowUpward} title='Move Down' onClick={this.moveDown} small={true} />
|
||||
<IconButton svg={DeleteOutlined} title='Remove' onClick={this.remove} small={true} />
|
||||
<IconButton svg={ArrowDownwardSvg} title='Move Up' onClick={this.moveUp} small={true} />
|
||||
<IconButton svg={ArrowUpwardSvg} title='Move Down' onClick={this.moveDown} small={true} />
|
||||
<IconButton svg={DeleteOutlinedSvg} title='Remove' onClick={this.remove} small={true} />
|
||||
</div>
|
||||
</div>
|
||||
{this.state.isExpanded && <div className='msp-control-offset'>
|
||||
|
||||
@@ -16,10 +16,9 @@ import { Volume, Grid } from '../../mol-model/volume';
|
||||
import { Vec3 } from '../../mol-math/linear-algebra';
|
||||
import { ColorNames } from '../../mol-util/color/names';
|
||||
import { toPrecision } from '../../mol-util/number';
|
||||
import VisibilityOffOutlined from '@material-ui/icons/VisibilityOffOutlined';
|
||||
import VisibilityOutlined from '@material-ui/icons/VisibilityOutlined';
|
||||
import { StateSelection, StateObjectCell } from '../../mol-state';
|
||||
import { setSubtreeVisibility } from '../../mol-plugin/behavior/static/state';
|
||||
import { VisibilityOutlinedSvg, VisibilityOffOutlinedSvg } from '../controls/icons';
|
||||
|
||||
const ChannelParams = {
|
||||
color: PD.Color(ColorNames.black, { description: 'Display color of the volume.' }),
|
||||
@@ -107,7 +106,7 @@ class Channel extends PluginUIComponent<{
|
||||
pivot={<div className='msp-volume-channel-inline-controls'>
|
||||
<Slider value={value} min={ctrlMin} max={ctrlMax} step={step}
|
||||
onChange={v => props.changeIso(props.name, v, isRelative)} disabled={props.params.isDisabled} onEnter={props.params.events.onEnter} />
|
||||
<IconButton svg={this.getVisible() ? VisibilityOutlined : VisibilityOffOutlined} onClick={this.toggleVisible} toggleState={false} disabled={props.params.isDisabled} />
|
||||
<IconButton svg={this.getVisible() ? VisibilityOutlinedSvg : VisibilityOffOutlinedSvg} onClick={this.toggleVisible} toggleState={false} disabled={props.params.isDisabled} />
|
||||
</div>}
|
||||
controls={<ParameterControls onChange={({ name, value }) => props.changeParams(props.name, name, value)} params={ChannelParams} values={channel} onEnter={props.params.events.onEnter} isDisabled={props.params.isDisabled} />}
|
||||
/>;
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import AccountTreeOutlined from '@material-ui/icons/AccountTreeOutlined';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import HelpOutline from '@material-ui/icons/HelpOutline';
|
||||
import HomeOutlined from '@material-ui/icons/HomeOutlined';
|
||||
import SaveOutlined from '@material-ui/icons/SaveOutlined';
|
||||
import Tune from '@material-ui/icons/Tune';
|
||||
import * as React from 'react';
|
||||
import { Canvas3DParams } from '../mol-canvas3d/canvas3d';
|
||||
import { PluginCommands } from '../mol-plugin/commands';
|
||||
@@ -23,6 +17,7 @@ import { StateObjectActions } from './state/actions';
|
||||
import { RemoteStateSnapshots, StateSnapshots } from './state/snapshots';
|
||||
import { StateTree } from './state/tree';
|
||||
import { HelpContent } from './viewport/help';
|
||||
import { HomeOutlinedSvg, AccountTreeOutlinedSvg, TuneSvg, HelpOutlineSvg, SaveOutlinedSvg, DeleteOutlinedSvg } from './controls/icons';
|
||||
|
||||
export class LeftPanelControls extends PluginUIComponent<{}, { tab: LeftPanelTabName }> {
|
||||
state = { tab: this.plugin.behaviors.layout.leftPanelTabName.value };
|
||||
@@ -57,21 +52,21 @@ export class LeftPanelControls extends PluginUIComponent<{}, { tab: LeftPanelTab
|
||||
tabs: { [K in LeftPanelTabName]: JSX.Element } = {
|
||||
'none': <></>,
|
||||
'root': <>
|
||||
<SectionHeader icon={HomeOutlined} title='Home' />
|
||||
<SectionHeader icon={HomeOutlinedSvg} title='Home' />
|
||||
<StateObjectActions state={this.plugin.state.data} nodeRef={StateTransform.RootRef} hideHeader={true} initiallyCollapsed={true} alwaysExpandFirst={true} />
|
||||
{this.plugin.spec.components?.remoteState !== 'none' && <RemoteStateSnapshots listOnly /> }
|
||||
</>,
|
||||
'data': <>
|
||||
<SectionHeader icon={AccountTreeOutlined} title={<><RemoveAllButton /> State Tree</>} />
|
||||
<SectionHeader icon={AccountTreeOutlinedSvg} title={<><RemoveAllButton /> State Tree</>} />
|
||||
<StateTree state={this.plugin.state.data} />
|
||||
</>,
|
||||
'states': <StateSnapshots />,
|
||||
'settings': <>
|
||||
<SectionHeader icon={Tune} title='Plugin Settings' />
|
||||
<SectionHeader icon={TuneSvg} title='Plugin Settings' />
|
||||
<FullSettings />
|
||||
</>,
|
||||
'help': <>
|
||||
<SectionHeader icon={HelpOutline} title='Help' />
|
||||
<SectionHeader icon={HelpOutlineSvg} title='Help' />
|
||||
<HelpContent />
|
||||
</>
|
||||
}
|
||||
@@ -81,12 +76,12 @@ export class LeftPanelControls extends PluginUIComponent<{}, { tab: LeftPanelTab
|
||||
|
||||
return <div className='msp-left-panel-controls'>
|
||||
<div className='msp-left-panel-controls-buttons'>
|
||||
<IconButton svg={HomeOutlined} toggleState={tab === 'root'} transparent onClick={() => this.set('root')} title='Home' />
|
||||
<IconButton svg={HomeOutlinedSvg} toggleState={tab === 'root'} transparent onClick={() => this.set('root')} title='Home' />
|
||||
<DataIcon set={this.set} />
|
||||
<IconButton svg={SaveOutlined} toggleState={tab === 'states'} transparent onClick={() => this.set('states')} title='Plugin State' />
|
||||
<IconButton svg={HelpOutline} toggleState={tab === 'help'} transparent onClick={() => this.set('help')} title='Help' />
|
||||
<IconButton svg={SaveOutlinedSvg} toggleState={tab === 'states'} transparent onClick={() => this.set('states')} title='Plugin State' />
|
||||
<IconButton svg={HelpOutlineSvg} toggleState={tab === 'help'} transparent onClick={() => this.set('help')} title='Help' />
|
||||
<div className='msp-left-panel-controls-buttons-bottom'>
|
||||
<IconButton svg={Tune} toggleState={tab === 'settings'} transparent onClick={() => this.set('settings')} title='Settings' />
|
||||
<IconButton svg={TuneSvg} toggleState={tab === 'settings'} transparent onClick={() => this.set('settings')} title='Settings' />
|
||||
</div>
|
||||
</div>
|
||||
<div className='msp-scrollable-container'>
|
||||
@@ -116,7 +111,7 @@ class DataIcon extends PluginUIComponent<{ set: (tab: LeftPanelTabName) => void
|
||||
|
||||
render() {
|
||||
return <IconButton
|
||||
svg={AccountTreeOutlined} toggleState={this.tab === 'data'} transparent onClick={() => this.props.set('data')} title='State Tree'
|
||||
svg={AccountTreeOutlinedSvg} toggleState={this.tab === 'data'} transparent onClick={() => this.props.set('data')} title='State Tree'
|
||||
style={{ position: 'relative' }} extraContent={this.state.changed ? <div className='msp-left-panel-controls-button-data-dirty' /> : void 0} />;
|
||||
}
|
||||
}
|
||||
@@ -168,6 +163,6 @@ class RemoveAllButton extends PluginUIComponent<{ }> {
|
||||
render() {
|
||||
const count = this.plugin.state.data.tree.children.get(StateTransform.RootRef).size;
|
||||
if (count === 0) return null;
|
||||
return <IconButton svg={DeleteOutlined} onClick={this.remove} title={'Remove All'} style={{ display: 'inline-block' }} small className='msp-no-hover-outline' transparent />;
|
||||
return <IconButton svg={DeleteOutlinedSvg} onClick={this.remove} title={'Remove All'} style={{ display: 'inline-block' }} small className='msp-no-hover-outline' transparent />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,8 @@ import { State, StateSelection } from '../mol-state';
|
||||
import { ChainSequenceWrapper } from './sequence/chain';
|
||||
import { ElementSequenceWrapper } from './sequence/element';
|
||||
import { elementLabel } from '../mol-theme/label';
|
||||
import { Icon } from './controls/icons';
|
||||
import { Icon, HelpOutlineSvg } from './controls/icons';
|
||||
import { StructureSelectionManager } from '../mol-plugin-state/manager/structure/selection';
|
||||
import HelpOutline from '@material-ui/icons/HelpOutline';
|
||||
|
||||
const MaxDisplaySequenceLength = 5000;
|
||||
|
||||
@@ -296,7 +295,7 @@ export class SequenceView extends PluginUIComponent<{ }, SequenceViewState> {
|
||||
if (this.getStructure(this.state.structureRef) === Structure.Empty) {
|
||||
return <div className='msp-sequence'>
|
||||
<div className='msp-sequence-select'>
|
||||
<Icon svg={HelpOutline} style={{ cursor: 'help', position: 'absolute', right: 0, top: 0 }}
|
||||
<Icon svg={HelpOutlineSvg} style={{ cursor: 'help', position: 'absolute', right: 0, top: 0 }}
|
||||
title='This shows a single sequence. Use the controls to show a different sequence.'/>
|
||||
|
||||
<span>Sequence</span><span style={{ fontWeight: 'normal' }}>No structure available</span>
|
||||
@@ -311,7 +310,7 @@ export class SequenceView extends PluginUIComponent<{ }, SequenceViewState> {
|
||||
|
||||
return <div className='msp-sequence'>
|
||||
<div className='msp-sequence-select'>
|
||||
<Icon svg={HelpOutline} style={{ cursor: 'help', position: 'absolute', right: 0, top: 0 }}
|
||||
<Icon svg={HelpOutlineSvg} style={{ cursor: 'help', position: 'absolute', right: 0, top: 0 }}
|
||||
title='This shows a single sequence. Use the controls to show a different sequence.' />
|
||||
|
||||
<span>Sequence of</span>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// @import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,700);
|
||||
|
||||
|
||||
@mixin user-select($select) {
|
||||
-webkit-user-select: $select;
|
||||
-moz-user-select: $select;
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
import * as React from 'react';
|
||||
import { State } from '../../mol-state';
|
||||
import { PluginUIComponent } from '../base';
|
||||
import { Icon } from '../controls/icons';
|
||||
import { Icon, CodeSvg } from '../controls/icons';
|
||||
import { ApplyActionControl } from './apply-action';
|
||||
import Code from '@material-ui/icons/Code';
|
||||
|
||||
export class StateObjectActions extends PluginUIComponent<{ state: State, nodeRef: string, hideHeader?: boolean, initiallyCollapsed?: boolean, alwaysExpandFirst?: boolean }> {
|
||||
get current() {
|
||||
@@ -42,7 +41,7 @@ export class StateObjectActions extends PluginUIComponent<{ state: State, nodeRe
|
||||
const display = cell.obj ? cell.obj.label : (def.display && def.display.name) || def.name;
|
||||
|
||||
return <div className='msp-state-actions'>
|
||||
{!this.props.hideHeader && <div className='msp-section-header'><Icon svg={Code} /> {`Actions (${display})`}</div> }
|
||||
{!this.props.hideHeader && <div className='msp-section-header'><Icon svg={CodeSvg} /> {`Actions (${display})`}</div> }
|
||||
{actions.map((act, i) => <ApplyActionControl
|
||||
key={`${act.id}`} state={state} action={act} nodeRef={ref}
|
||||
initiallyCollapsed={i === 0 ? !this.props.alwaysExpandFirst && this.props.initiallyCollapsed : this.props.initiallyCollapsed} />)}
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as React from 'react';
|
||||
import { PluginUIComponent } from '../base';
|
||||
import { ParameterControls, ParamOnChange } from '../controls/parameters';
|
||||
import { Button } from '../controls/common';
|
||||
import PlayArrow from '@material-ui/icons/PlayArrow';
|
||||
import { PlayArrowSvg } from '../controls/icons';
|
||||
|
||||
export class AnimationControls extends PluginUIComponent<{ onStart?: () => void }> {
|
||||
componentDidMount() {
|
||||
@@ -44,7 +44,7 @@ export class AnimationControls extends PluginUIComponent<{ onStart?: () => void
|
||||
<ParameterControls params={anim.current.params} values={anim.current.paramValues} onChange={this.updateCurrentParams} isDisabled={isDisabled} />
|
||||
|
||||
<div className='msp-flex-row'>
|
||||
<Button icon={anim.state.animationState !== 'playing' ? void 0 : PlayArrow} onClick={this.startOrStop} disabled={canApply !== void 0 && canApply.canApply === false}>
|
||||
<Button icon={anim.state.animationState !== 'playing' ? void 0 : PlayArrowSvg} onClick={this.startOrStop} disabled={canApply !== void 0 && canApply.canApply === false}>
|
||||
{anim.state.animationState === 'playing' ? 'Stop' : canApply === void 0 || canApply.canApply ? 'Start' : canApply.reason || 'Start'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -11,13 +11,8 @@ import { ParameterControls, ParamOnChange } from '../controls/parameters';
|
||||
import { PluginContext } from '../../mol-plugin/context';
|
||||
import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Icon } from '../controls/icons';
|
||||
import { Icon, RefreshSvg, CheckSvg, ArrowRightSvg, ArrowDropDownSvg, TuneSvg } from '../controls/icons';
|
||||
import { ExpandGroup, ToggleButton, Button, IconButton } from '../controls/common';
|
||||
import Refresh from '@material-ui/icons/Refresh';
|
||||
import ArrowRight from '@material-ui/icons/ArrowRight';
|
||||
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
|
||||
import Check from '@material-ui/icons/Check';
|
||||
import Tune from '@material-ui/icons/Tune';
|
||||
|
||||
export { StateTransformParameters, TransformControlBase };
|
||||
|
||||
@@ -199,9 +194,9 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
|
||||
if (this.props.autoHideApply && (!canApply || this.canAutoApply(this.state.params))) return null;
|
||||
|
||||
return <div className='msp-transform-apply-wrap'>
|
||||
<IconButton svg={Refresh} className='msp-transform-default-params' onClick={this.setDefault} disabled={this.state.busy} title='Set default params' />
|
||||
<IconButton svg={RefreshSvg} className='msp-transform-default-params' onClick={this.setDefault} disabled={this.state.busy} title='Set default params' />
|
||||
<div className={`msp-transform-apply-wider`}>
|
||||
<Button icon={canApply ? Check : void 0} className={`msp-btn-commit msp-btn-commit-${canApply ? 'on' : 'off'}`} onClick={this.apply} disabled={!canApply}>
|
||||
<Button icon={canApply ? CheckSvg : void 0} className={`msp-btn-commit msp-btn-commit-${canApply ? 'on' : 'off'}`} onClick={this.apply} disabled={!canApply}>
|
||||
{this.props.applyLabel || this.applyText()}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -236,7 +231,7 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
|
||||
const ctrl = <div className={wrapClass} style={{ marginBottom: this.props.noMargin ? 0 : void 0 }}>
|
||||
{display !== 'none' && !this.props.wrapInExpander && <div className='msp-transform-header'>
|
||||
<Button onClick={this.toggleExpanded} title={display.description}>
|
||||
{!isEmpty && <Icon svg={this.state.isCollapsed ? ArrowRight : ArrowDropDown} />}
|
||||
{!isEmpty && <Icon svg={this.state.isCollapsed ? ArrowRightSvg : ArrowDropDownSvg} />}
|
||||
{display.name}
|
||||
</Button>
|
||||
</div>}
|
||||
@@ -258,7 +253,7 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS
|
||||
<Button icon={this.props.simpleApply?.icon} title={this.props.simpleApply?.title} disabled={this.state.busy || !canApply} onClick={this.apply} className='msp-btn-apply-simple'>
|
||||
{this.props.simpleApply?.header}
|
||||
</Button>
|
||||
{!info.isEmpty && <ToggleButton icon={Tune} label='' title='Options' toggle={this.toggleExpanded} isSelected={!this.state.isCollapsed} disabled={this.state.busy} style={{ flex: '0 0 40px', padding: 0 }} />}
|
||||
{!info.isEmpty && <ToggleButton icon={TuneSvg} label='' title='Options' toggle={this.toggleExpanded} isSelected={!this.state.isCollapsed} disabled={this.state.busy} style={{ flex: '0 0 40px', padding: 0 }} />}
|
||||
</div>;
|
||||
|
||||
if (this.state.isCollapsed) return apply;
|
||||
|
||||
@@ -4,17 +4,6 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import Add from '@material-ui/icons/Refresh';
|
||||
import ArrowDownward from '@material-ui/icons/ArrowDownward';
|
||||
import ArrowUpward from '@material-ui/icons/ArrowUpward';
|
||||
import CloudUpload from '@material-ui/icons/CloudUpload';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import GetApp from '@material-ui/icons/GetApp';
|
||||
import OpenInBrowser from '@material-ui/icons/OpenInBrowser';
|
||||
import SaveOutlined from '@material-ui/icons/SaveOutlined';
|
||||
import SwapHoriz from '@material-ui/icons/SwapHoriz';
|
||||
import Refresh from '@material-ui/icons/Refresh';
|
||||
import Warning from '@material-ui/icons/Warning';
|
||||
import { OrderedMap } from 'immutable';
|
||||
import * as React from 'react';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
@@ -26,13 +15,13 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
||||
import { urlCombine } from '../../mol-util/url';
|
||||
import { PluginUIComponent, PurePluginUIComponent } from '../base';
|
||||
import { Button, ExpandGroup, IconButton, SectionHeader } from '../controls/common';
|
||||
import { Icon } from '../controls/icons';
|
||||
import { Icon, SaveOutlinedSvg, GetAppSvg, OpenInBrowserSvg, WarningSvg, DeleteOutlinedSvg, AddSvg, ArrowUpwardSvg, SwapHorizSvg, ArrowDownwardSvg, RefreshSvg, CloudUploadSvg } from '../controls/icons';
|
||||
import { ParameterControls } from '../controls/parameters';
|
||||
|
||||
export class StateSnapshots extends PluginUIComponent<{}> {
|
||||
render() {
|
||||
return <div>
|
||||
<SectionHeader icon={SaveOutlined} title='Plugin State' />
|
||||
<SectionHeader icon={SaveOutlinedSvg} title='Plugin State' />
|
||||
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
<ExpandGroup header='Save Options' initiallyExpanded={false}>
|
||||
@@ -76,18 +65,18 @@ export class StateExportImportControls extends PluginUIComponent<{ onAction?: ()
|
||||
render() {
|
||||
return <>
|
||||
<div className='msp-flex-row'>
|
||||
<Button icon={GetApp} onClick={this.downloadToFileJson} title='Save the state description. Input data are loaded using the provided sources. Does not work if local files are used as input.'>
|
||||
<Button icon={GetAppSvg} onClick={this.downloadToFileJson} title='Save the state description. Input data are loaded using the provided sources. Does not work if local files are used as input.'>
|
||||
State
|
||||
</Button>
|
||||
<Button icon={GetApp} onClick={this.downloadToFileZip} title='Save the state including the input data.'>
|
||||
<Button icon={GetAppSvg} onClick={this.downloadToFileZip} title='Save the state including the input data.'>
|
||||
Session
|
||||
</Button>
|
||||
<div className='msp-btn msp-btn-block msp-btn-action msp-loader-msp-btn-file'>
|
||||
<Icon svg={OpenInBrowser} inline /> Open <input onChange={this.open} type='file' multiple={false} accept='.molx,.molj' />
|
||||
<Icon svg={OpenInBrowserSvg} inline /> Open <input onChange={this.open} type='file' multiple={false} accept='.molx,.molj' />
|
||||
</div>
|
||||
</div>
|
||||
<div className='msp-help-text' style={{ padding: '10px'}}>
|
||||
<Icon svg={Warning} /> This is an experimental feature and stored states/sessions might not be openable in a future version.
|
||||
<Icon svg={WarningSvg} /> This is an experimental feature and stored states/sessions might not be openable in a future version.
|
||||
</div>
|
||||
</>;
|
||||
}
|
||||
@@ -134,8 +123,8 @@ class LocalStateSnapshots extends PluginUIComponent<
|
||||
return <div>
|
||||
<ParameterControls params={LocalStateSnapshots.Params} values={this.state.params} onEnter={this.add} onChangeValues={this.updateParams} />
|
||||
<div className='msp-flex-row'>
|
||||
<IconButton onClick={this.clear} svg={DeleteOutlined} title='Remove All' />
|
||||
<Button onClick={this.add} icon={Add} style={{ textAlign: 'right' }} commit>Add</Button>
|
||||
<IconButton onClick={this.clear} svg={DeleteOutlinedSvg} title='Remove All' />
|
||||
<Button onClick={this.add} icon={AddSvg} style={{ textAlign: 'right' }} commit>Add</Button>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
@@ -186,10 +175,10 @@ class LocalStateSnapshotList extends PluginUIComponent<{}, {}> {
|
||||
{`${e!.snapshot.durationInMs ? formatTimespan(e!.snapshot.durationInMs, false) + `${e!.description ? ', ' : ''}` : ''}${e!.description ? e!.description : ''}`}
|
||||
</small>
|
||||
</Button>
|
||||
<IconButton svg={ArrowUpward} data-id={e!.snapshot.id} title='Move Up' onClick={this.moveUp} flex='20px' />
|
||||
<IconButton svg={ArrowDownward} data-id={e!.snapshot.id} title='Move Down' onClick={this.moveDown} flex='20px' />
|
||||
<IconButton svg={SwapHoriz} data-id={e!.snapshot.id} title='Replace' onClick={this.replace} flex='20px' />
|
||||
<IconButton svg={DeleteOutlined} data-id={e!.snapshot.id} title='Remove' onClick={this.remove} flex='20px' />
|
||||
<IconButton svg={ArrowUpwardSvg} data-id={e!.snapshot.id} title='Move Up' onClick={this.moveUp} flex='20px' />
|
||||
<IconButton svg={ArrowDownwardSvg} data-id={e!.snapshot.id} title='Move Down' onClick={this.moveDown} flex='20px' />
|
||||
<IconButton svg={SwapHorizSvg} data-id={e!.snapshot.id} title='Replace' onClick={this.replace} flex='20px' />
|
||||
<IconButton svg={DeleteOutlinedSvg} data-id={e!.snapshot.id} title='Remove' onClick={this.remove} flex='20px' />
|
||||
</li>)}
|
||||
</ul>;
|
||||
}
|
||||
@@ -317,8 +306,8 @@ export class RemoteStateSnapshots extends PluginUIComponent<
|
||||
this.setState({ params: { ...this.state.params, [p.name]: p.value } } as any);
|
||||
}} isDisabled={this.state.isBusy} />
|
||||
<div className='msp-flex-row'>
|
||||
<IconButton onClick={this.refresh} disabled={this.state.isBusy} svg={Refresh} />
|
||||
<Button icon={CloudUpload} onClick={this.upload} disabled={this.state.isBusy} commit>Upload</Button>
|
||||
<IconButton onClick={this.refresh} disabled={this.state.isBusy} svg={RefreshSvg} />
|
||||
<Button icon={CloudUploadSvg} onClick={this.upload} disabled={this.state.isBusy} commit>Upload</Button>
|
||||
</div>
|
||||
</>}
|
||||
|
||||
@@ -330,7 +319,7 @@ export class RemoteStateSnapshots extends PluginUIComponent<
|
||||
this.setState({ params: { ...this.state.params, [p.name]: p.value } } as any);
|
||||
}} isDisabled={this.state.isBusy} />
|
||||
<div className='msp-flex-row'>
|
||||
<Button onClick={this.refresh} disabled={this.state.isBusy} icon={Refresh}>Refresh</Button>
|
||||
<Button onClick={this.refresh} disabled={this.state.isBusy} icon={RefreshSvg}>Refresh</Button>
|
||||
</div>
|
||||
</div>}
|
||||
</>;
|
||||
@@ -361,7 +350,7 @@ class RemoteStateSnapshotList extends PurePluginUIComponent<
|
||||
disabled={this.props.isBusy} onContextMenu={this.open} title='Click to download, right-click to open in a new tab.'>
|
||||
{e!.name || new Date(e!.timestamp).toLocaleString()} <small>{e!.description}</small>
|
||||
</Button>
|
||||
{!e!.isSticky && this.props.remove && <IconButton svg={DeleteOutlined} data-id={e!.id} title='Remove' onClick={this.props.remove} disabled={this.props.isBusy} small />}
|
||||
{!e!.isSticky && this.props.remove && <IconButton svg={DeleteOutlinedSvg} data-id={e!.id} title='Remove' onClick={this.props.remove} disabled={this.props.isBusy} small />}
|
||||
</li>)}
|
||||
</ul>;
|
||||
}
|
||||
|
||||
@@ -4,13 +4,6 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
|
||||
import ArrowRight from '@material-ui/icons/ArrowRight';
|
||||
import Close from '@material-ui/icons/Close';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import HomeOutlined from '@material-ui/icons/HomeOutlined';
|
||||
import VisibilityOffOutlined from '@material-ui/icons/VisibilityOffOutlined';
|
||||
import VisibilityOutlined from '@material-ui/icons/VisibilityOutlined';
|
||||
import * as React from 'react';
|
||||
import { debounceTime, filter } from 'rxjs/operators';
|
||||
import { PluginStateObject } from '../../mol-plugin-state/objects';
|
||||
@@ -20,7 +13,7 @@ import { StateTreeSpine } from '../../mol-state/tree/spine';
|
||||
import { PluginUIComponent, _Props, _State } from '../base';
|
||||
import { ActionMenu } from '../controls/action-menu';
|
||||
import { Button, ControlGroup, IconButton } from '../controls/common';
|
||||
import { Icon } from '../controls/icons';
|
||||
import { Icon, HomeOutlinedSvg, ArrowRightSvg, ArrowDropDownSvg, DeleteOutlinedSvg, VisibilityOffOutlinedSvg, VisibilityOutlinedSvg, CloseSvg } from '../controls/icons';
|
||||
import { ApplyActionControl } from './apply-action';
|
||||
import { UpdateTransformControl } from './update-transform';
|
||||
|
||||
@@ -50,7 +43,7 @@ export class StateTree extends PluginUIComponent<{ state: State }, { showActions
|
||||
if (this.state.showActions) {
|
||||
return <div style={{ margin: '10px', cursor: 'default' }}>
|
||||
<p>Nothing to see here yet.</p>
|
||||
<p>Structures and Volumes can be loaded from the <Icon svg={HomeOutlined} /> tab.</p>
|
||||
<p>Structures and Volumes can be loaded from the <Icon svg={HomeOutlinedSvg} /> tab.</p>
|
||||
</div>;
|
||||
}
|
||||
return <StateTreeNode cell={this.props.state.cells.get(ref)!} depth={0} />;
|
||||
@@ -306,9 +299,9 @@ class StateTreeNodeLabel extends PluginUIComponent<{ cell: StateObjectCell, dept
|
||||
const children = cell.parent!.tree.children.get(this.ref);
|
||||
const cellState = cell.state;
|
||||
|
||||
const expand = <IconButton svg={cellState.isCollapsed ? ArrowRight : ArrowDropDown} flex='20px' disabled={disabled} onClick={this.toggleExpanded} transparent className='msp-no-hover-outline' style={{ visibility: children.size > 0 ? 'visible' : 'hidden' }} />;
|
||||
const remove = !cell.state.isLocked ? <IconButton svg={DeleteOutlined} onClick={this.remove} disabled={disabled} small toggleState={false} /> : void 0;
|
||||
const visibility = <IconButton svg={cellState.isHidden ? VisibilityOffOutlined : VisibilityOutlined} toggleState={false} disabled={disabled} small onClick={this.toggleVisible} />;
|
||||
const expand = <IconButton svg={cellState.isCollapsed ? ArrowRightSvg : ArrowDropDownSvg} flex='20px' disabled={disabled} onClick={this.toggleExpanded} transparent className='msp-no-hover-outline' style={{ visibility: children.size > 0 ? 'visible' : 'hidden' }} />;
|
||||
const remove = !cell.state.isLocked ? <IconButton svg={DeleteOutlinedSvg} onClick={this.remove} disabled={disabled} small toggleState={false} /> : void 0;
|
||||
const visibility = <IconButton svg={cellState.isHidden ? VisibilityOffOutlinedSvg : VisibilityOutlinedSvg} toggleState={false} disabled={disabled} small onClick={this.toggleVisible} />;
|
||||
|
||||
const marginStyle: React.CSSProperties = {
|
||||
marginLeft: `${this.props.depth * 8}px`
|
||||
@@ -326,7 +319,7 @@ class StateTreeNodeLabel extends PluginUIComponent<{ cell: StateObjectCell, dept
|
||||
if (this.state.action === 'apply' && this.state.currentAction) {
|
||||
return <div style={{ marginBottom: '1px' }}>
|
||||
{row}
|
||||
<ControlGroup header={`Apply ${this.state.currentAction.definition.display.name}`} initialExpanded={true} hideExpander={true} hideOffset={false} onHeaderClick={this.hideApply} topRightIcon={Close} headerLeftMargin={`${this.props.depth * 8 + 21}px`}>
|
||||
<ControlGroup header={`Apply ${this.state.currentAction.definition.display.name}`} initialExpanded={true} hideExpander={true} hideOffset={false} onHeaderClick={this.hideApply} topRightIcon={CloseSvg} headerLeftMargin={`${this.props.depth * 8 + 21}px`}>
|
||||
<ApplyActionControl onApply={this.hideApply} state={this.props.cell.parent!} action={this.state.currentAction} nodeRef={this.props.cell.transform.ref} hideHeader noMargin />
|
||||
</ControlGroup>
|
||||
</div>;
|
||||
|
||||
@@ -4,15 +4,6 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import Add from '@material-ui/icons/Add';
|
||||
import BookmarksOutlined from '@material-ui/icons/BookmarksOutlined';
|
||||
import Delete from '@material-ui/icons/Delete';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import MoreHoriz from '@material-ui/icons/MoreHoriz';
|
||||
import Restore from '@material-ui/icons/Restore';
|
||||
import Tune from '@material-ui/icons/Tune';
|
||||
import VisibilityOffOutlined from '@material-ui/icons/VisibilityOffOutlined';
|
||||
import VisibilityOutlined from '@material-ui/icons/VisibilityOutlined';
|
||||
import * as React from 'react';
|
||||
import { getStructureThemeTypes } from '../../mol-plugin-state/helpers/structure-representation-params';
|
||||
import { StructureComponentManager } from '../../mol-plugin-state/manager/structure/component';
|
||||
@@ -24,7 +15,7 @@ import { ParamDefinition } from '../../mol-util/param-definition';
|
||||
import { CollapsableControls, CollapsableState, PurePluginUIComponent } from '../base';
|
||||
import { ActionMenu } from '../controls/action-menu';
|
||||
import { Button, ExpandGroup, IconButton, ToggleButton } from '../controls/common';
|
||||
import { CubeSvg, Intersect, SetSvg, Subtract, Union } from '../controls/icons';
|
||||
import { CubeSvg, IntersectSvg, SetSvg, SubtractSvg, UnionSvg, BookmarksOutlinedSvg, AddSvg, TuneSvg, RestoreSvg, DeleteSvg, VisibilityOffOutlinedSvg, VisibilityOutlinedSvg, DeleteOutlinedSvg, MoreHorizSvg } from '../controls/icons';
|
||||
import { ParameterControls } from '../controls/parameters';
|
||||
import { UpdateTransformControl } from '../state/update-transform';
|
||||
import { GenericEntryListControls } from './generic';
|
||||
@@ -130,10 +121,10 @@ class ComponentEditorControls extends PurePluginUIComponent<{}, ComponentEditorC
|
||||
: 'Some mistakes of the past can be undone.';
|
||||
return <>
|
||||
<div className='msp-flex-row'>
|
||||
<ToggleButton icon={BookmarksOutlined} label='Preset' title='Apply a representation preset for the current structure(s).' toggle={this.togglePreset} isSelected={this.state.action === 'preset'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={Add} label='Add' title='Add a new representation component for a selection.' toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={Tune} label='' title='Options that are applied to all applicable representations.' style={{ flex: '0 0 40px', padding: 0 }} toggle={this.toggleOptions} isSelected={this.state.action === 'options'} disabled={this.isDisabled} />
|
||||
<IconButton svg={Restore} className='msp-flex-item' flex='40px' onClick={this.undo} disabled={!this.state.canUndo || this.isDisabled} title={undoTitle} />
|
||||
<ToggleButton icon={BookmarksOutlinedSvg} label='Preset' title='Apply a representation preset for the current structure(s).' toggle={this.togglePreset} isSelected={this.state.action === 'preset'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={AddSvg} label='Add' title='Add a new representation component for a selection.' toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={TuneSvg} label='' title='Options that are applied to all applicable representations.' style={{ flex: '0 0 40px', padding: 0 }} toggle={this.toggleOptions} isSelected={this.state.action === 'options'} disabled={this.isDisabled} />
|
||||
<IconButton svg={RestoreSvg} className='msp-flex-item' flex='40px' onClick={this.undo} disabled={!this.state.canUndo || this.isDisabled} title={undoTitle} />
|
||||
</div>
|
||||
{this.state.action === 'preset' && this.presetControls}
|
||||
{this.state.action === 'add' && <div className='msp-control-offset'>
|
||||
@@ -179,7 +170,7 @@ export class AddComponentControls extends PurePluginUIComponent<AddComponentCont
|
||||
render() {
|
||||
return <>
|
||||
<ParameterControls params={this.state.params} values={this.state.values} onChangeValues={this.paramsChanged} />
|
||||
<Button icon={Add} title='Use Selection and optional Representation to create a new Component.' className='msp-btn-commit msp-btn-commit-on' onClick={this.apply} style={{ marginTop: '1px' }}>
|
||||
<Button icon={AddSvg} title='Use Selection and optional Representation to create a new Component.' className='msp-btn-commit msp-btn-commit-on' onClick={this.apply} style={{ marginTop: '1px' }}>
|
||||
Create Component
|
||||
</Button>
|
||||
</>;
|
||||
@@ -267,9 +258,9 @@ class StructureComponentGroup extends PurePluginUIComponent<{ group: StructureCo
|
||||
if (mng.canBeModified(this.props.group[0])) {
|
||||
ret.push([
|
||||
ActionMenu.Header('Modify by Selection'),
|
||||
ActionMenu.Item('Include', () => mng.modifyByCurrentSelection(this.props.group, 'union'), { icon: Union }),
|
||||
ActionMenu.Item('Subtract', () => mng.modifyByCurrentSelection(this.props.group, 'subtract'), { icon: Subtract }),
|
||||
ActionMenu.Item('Intersect', () => mng.modifyByCurrentSelection(this.props.group, 'intersect'), { icon: Intersect })
|
||||
ActionMenu.Item('Include', () => mng.modifyByCurrentSelection(this.props.group, 'union'), { icon: UnionSvg }),
|
||||
ActionMenu.Item('Subtract', () => mng.modifyByCurrentSelection(this.props.group, 'subtract'), { icon: SubtractSvg }),
|
||||
ActionMenu.Item('Intersect', () => mng.modifyByCurrentSelection(this.props.group, 'intersect'), { icon: IntersectSvg })
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -286,7 +277,7 @@ class StructureComponentGroup extends PurePluginUIComponent<{ group: StructureCo
|
||||
|
||||
get removeActions(): ActionMenu.Items {
|
||||
const ret = [
|
||||
ActionMenu.Item('Remove', () => this.plugin.managers.structure.hierarchy.remove(this.props.group, true), { icon: Delete })
|
||||
ActionMenu.Item('Remove', () => this.plugin.managers.structure.hierarchy.remove(this.props.group, true), { icon: DeleteSvg })
|
||||
];
|
||||
|
||||
const reprs = this.pivot.representations;
|
||||
@@ -294,7 +285,7 @@ class StructureComponentGroup extends PurePluginUIComponent<{ group: StructureCo
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.push(ActionMenu.Item(`Remove Representation${reprs.length > 1 ? 's' : ''}`, () => this.plugin.managers.structure.component.removeRepresentations(this.props.group), { icon: Delete }));
|
||||
ret.push(ActionMenu.Item(`Remove Representation${reprs.length > 1 ? 's' : ''}`, () => this.plugin.managers.structure.component.removeRepresentations(this.props.group), { icon: DeleteSvg }));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -357,9 +348,9 @@ class StructureComponentGroup extends PurePluginUIComponent<{ group: StructureCo
|
||||
{label}
|
||||
<small className='msp-25-lower-contrast-text' style={{ float: 'right' }}>{reprLabel}</small>
|
||||
</Button>
|
||||
<IconButton svg={cell.state.isHidden ? VisibilityOffOutlined : VisibilityOutlined} toggleState={false} onClick={this.toggleVisible} title={`${cell.state.isHidden ? 'Show' : 'Hide'} component`} small className='msp-form-control' flex />
|
||||
<IconButton svg={DeleteOutlined} onClick={this.toggleRemove} title='Remove' small toggleState={this.state.action === 'remove'} className='msp-form-control' flex />
|
||||
<IconButton svg={MoreHoriz} onClick={this.toggleAction} title='Actions' toggleState={this.state.action === 'action'} className='msp-form-control' flex />
|
||||
<IconButton svg={cell.state.isHidden ? VisibilityOffOutlinedSvg : VisibilityOutlinedSvg} toggleState={false} onClick={this.toggleVisible} title={`${cell.state.isHidden ? 'Show' : 'Hide'} component`} small className='msp-form-control' flex />
|
||||
<IconButton svg={DeleteOutlinedSvg} onClick={this.toggleRemove} title='Remove' small toggleState={this.state.action === 'remove'} className='msp-form-control' flex />
|
||||
<IconButton svg={MoreHorizSvg} onClick={this.toggleAction} title='Actions' toggleState={this.state.action === 'action'} className='msp-form-control' flex />
|
||||
</div>
|
||||
{this.state.action === 'remove' && <div style={{ marginBottom: '6px' }}>
|
||||
<ActionMenu items={this.removeActions} onSelect={this.selectRemoveAction} />
|
||||
@@ -398,10 +389,10 @@ class StructureRepresentationEntry extends PurePluginUIComponent<{ group: Struct
|
||||
{repr.parent && <ExpandGroup header={`${repr.obj?.label || ''} Representation`} noOffset>
|
||||
<UpdateTransformControl state={repr.parent} transform={repr.transform} customHeader='none' customUpdate={this.update} noMargin />
|
||||
</ExpandGroup>}
|
||||
<IconButton svg={DeleteOutlined} onClick={this.remove} title='Remove' small className='msp-default-bg' toggleState={false} style={{
|
||||
<IconButton svg={DeleteOutlinedSvg} onClick={this.remove} title='Remove' small className='msp-default-bg' toggleState={false} style={{
|
||||
position: 'absolute', top: 0, right: '32px', lineHeight: '24px', height: '24px', textAlign: 'right', width: '44px', paddingRight: '6px', background: 'none'
|
||||
}} />
|
||||
<IconButton svg={this.props.representation.cell.state.isHidden ? VisibilityOffOutlined : VisibilityOutlined} toggleState={false} onClick={this.toggleVisible} title='Toggle Visibility' small className='msp-default-bg' style={{
|
||||
<IconButton svg={this.props.representation.cell.state.isHidden ? VisibilityOffOutlinedSvg : VisibilityOutlinedSvg} toggleState={false} onClick={this.toggleVisible} title='Toggle Visibility' small className='msp-default-bg' style={{
|
||||
position: 'absolute', top: 0, right: 0, lineHeight: '24px', height: '24px', textAlign: 'right', width: '32px', paddingRight: '6px', background: 'none'
|
||||
}} />
|
||||
</div>;
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import CenterFocusStrong from '@material-ui/icons/CenterFocusStrong';
|
||||
import CancelOutlined from '@material-ui/icons/CancelOutlined';
|
||||
import * as React from 'react';
|
||||
import { OrderedSet, SortedArray } from '../../mol-data/int';
|
||||
import { MmcifFormat } from '../../mol-model-formats/structure/mmcif';
|
||||
@@ -21,6 +19,7 @@ import { memoizeLatest } from '../../mol-util/memoize';
|
||||
import { PluginUIComponent } from '../base';
|
||||
import { ActionMenu } from '../controls/action-menu';
|
||||
import { Button, IconButton, ToggleButton } from '../controls/common';
|
||||
import { CancelOutlinedSvg, CenterFocusStrongSvg } from '../controls/icons';
|
||||
|
||||
interface StructureFocusControlsState {
|
||||
isBusy: boolean
|
||||
@@ -238,8 +237,8 @@ export class StructureFocusControls extends PluginUIComponent<{}, StructureFocus
|
||||
style={{ textAlignLast: current ? 'left' : void 0 }}>
|
||||
{label}
|
||||
</Button>
|
||||
{current && <IconButton svg={CancelOutlined} onClick={this.clear} title='Clear' className='msp-form-control' flex disabled={this.isDisabled} />}
|
||||
<ToggleButton icon={CenterFocusStrong} title='Select a focus target to center on an show its surroundings. Hold shift to focus on multiple targets.' toggle={this.toggleAction} isSelected={this.state.showAction} disabled={this.isDisabled} style={{ flex: '0 0 40px', padding: 0 }} />
|
||||
{current && <IconButton svg={CancelOutlinedSvg} onClick={this.clear} title='Clear' className='msp-form-control' flex disabled={this.isDisabled} />}
|
||||
<ToggleButton icon={CenterFocusStrongSvg} title='Select a focus target to center on an show its surroundings. Hold shift to focus on multiple targets.' toggle={this.toggleAction} isSelected={this.state.showAction} disabled={this.isDisabled} style={{ flex: '0 0 40px', padding: 0 }} />
|
||||
</div>
|
||||
{this.state.showAction && <ActionMenu items={this.actionItems} onSelect={this.selectAction} />}
|
||||
</>;
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import MoreHoriz from '@material-ui/icons/MoreHoriz';
|
||||
import VisibilityOutlined from '@material-ui/icons/VisibilityOutlined';
|
||||
import VisibilityOffOutlined from '@material-ui/icons/VisibilityOffOutlined';
|
||||
import * as React from 'react';
|
||||
import { StructureHierarchyRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
@@ -15,6 +12,7 @@ import { State } from '../../mol-state';
|
||||
import { PurePluginUIComponent } from '../base';
|
||||
import { IconButton } from '../controls/common';
|
||||
import { UpdateTransformControl } from '../state/update-transform';
|
||||
import { VisibilityOffOutlinedSvg, VisibilityOutlinedSvg, MoreHorizSvg } from '../controls/icons';
|
||||
|
||||
export class GenericEntryListControls extends PurePluginUIComponent {
|
||||
get current() {
|
||||
@@ -143,8 +141,8 @@ export class GenericEntry<T extends StructureHierarchyRef> extends PurePluginUIC
|
||||
<button className='msp-form-control msp-control-button-label' title={`${label}. Click to focus.`} onClick={this.focus} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight} style={{ textAlign: 'left' }}>
|
||||
{label} <small>{description}</small>
|
||||
</button>
|
||||
<IconButton svg={pivot.cell.state.isHidden ? VisibilityOffOutlined : VisibilityOutlined} toggleState={false} className='msp-form-control' onClick={this.toggleVisibility} title={`${pivot.cell.state.isHidden ? 'Show' : 'Hide'}`} small flex />
|
||||
{refs.length === 1 && <IconButton svg={MoreHoriz} className='msp-form-control' onClick={this.toggleOptions} title='Options' toggleState={this.state.showOptions} flex />}
|
||||
<IconButton svg={pivot.cell.state.isHidden ? VisibilityOffOutlinedSvg : VisibilityOutlinedSvg} toggleState={false} className='msp-form-control' onClick={this.toggleVisibility} title={`${pivot.cell.state.isHidden ? 'Show' : 'Hide'}`} small flex />
|
||||
{refs.length === 1 && <IconButton svg={MoreHorizSvg} className='msp-form-control' onClick={this.toggleOptions} title='Options' toggleState={this.state.showOptions} flex />}
|
||||
</div>
|
||||
{(refs.length === 1 && this.state.showOptions && pivot.cell.parent) && <>
|
||||
<div className='msp-control-offset'>
|
||||
|
||||
@@ -5,15 +5,6 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import Add from '@material-ui/icons/Add';
|
||||
import ArrowDownward from '@material-ui/icons/ArrowDownward';
|
||||
import ArrowUpward from '@material-ui/icons/ArrowUpward';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import HelpOutline from '@material-ui/icons/HelpOutline';
|
||||
import MoreHoriz from '@material-ui/icons/MoreHoriz';
|
||||
import Tune from '@material-ui/icons/Tune';
|
||||
import VisibilityOffOutlined from '@material-ui/icons/VisibilityOffOutlined';
|
||||
import VisibilityOutlined from '@material-ui/icons/VisibilityOutlined';
|
||||
import * as React from 'react';
|
||||
import { Loci } from '../../mol-model/loci';
|
||||
import { StructureElement } from '../../mol-model/structure';
|
||||
@@ -26,7 +17,7 @@ import { FiniteArray } from '../../mol-util/type-helpers';
|
||||
import { CollapsableControls, PurePluginUIComponent } from '../base';
|
||||
import { ActionMenu } from '../controls/action-menu';
|
||||
import { Button, ExpandGroup, IconButton, ToggleButton } from '../controls/common';
|
||||
import { Icon, RulerSvg, SetSvg } from '../controls/icons';
|
||||
import { Icon, RulerSvg, SetSvg, ArrowUpwardSvg, ArrowDownwardSvg, DeleteOutlinedSvg, HelpOutlineSvg, AddSvg, TuneSvg, VisibilityOffOutlinedSvg, VisibilityOutlinedSvg, MoreHorizSvg } from '../controls/icons';
|
||||
import { ParameterControls } from '../controls/parameters';
|
||||
import { UpdateTransformControl } from '../state/update-transform';
|
||||
import { ToggleSelectionModeButton } from './selection';
|
||||
@@ -152,9 +143,9 @@ export class MeasurementControls extends PurePluginUIComponent<{}, { isBusy: boo
|
||||
<Button noOverflow title='Click to focus. Hover to highlight.' onClick={() => this.focusLoci(e.loci)} style={{ width: 'auto', textAlign: 'left' }} onMouseEnter={() => this.highlight(e.loci)} onMouseLeave={this.plugin.managers.interactivity.lociHighlights.clearHighlights}>
|
||||
{idx}. <span dangerouslySetInnerHTML={{ __html: e.label }} />
|
||||
</Button>
|
||||
{history.length > 1 && <IconButton svg={ArrowUpward} small={true} className='msp-form-control' onClick={() => this.moveHistory(e, 'up')} flex='20px' title={'Move up'} />}
|
||||
{history.length > 1 && <IconButton svg={ArrowDownward} small={true} className='msp-form-control' onClick={() => this.moveHistory(e, 'down')} flex='20px' title={'Move down'} />}
|
||||
<IconButton svg={DeleteOutlined} small={true} className='msp-form-control' onClick={() => this.plugin.managers.structure.selection.modifyHistory(e, 'remove')} flex title={'Remove'} />
|
||||
{history.length > 1 && <IconButton svg={ArrowUpwardSvg} small={true} className='msp-form-control' onClick={() => this.moveHistory(e, 'up')} flex='20px' title={'Move up'} />}
|
||||
{history.length > 1 && <IconButton svg={ArrowDownwardSvg} small={true} className='msp-form-control' onClick={() => this.moveHistory(e, 'down')} flex='20px' title={'Move down'} />}
|
||||
<IconButton svg={DeleteOutlinedSvg} small={true} className='msp-form-control' onClick={() => this.plugin.managers.structure.selection.modifyHistory(e, 'remove')} flex title={'Remove'} />
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -172,7 +163,7 @@ export class MeasurementControls extends PurePluginUIComponent<{}, { isBusy: boo
|
||||
{entries}
|
||||
</div>}
|
||||
{entries.length === 0 && <div className='msp-control-offset msp-help-text'>
|
||||
<div className='msp-help-description' style={{ padding: 0 }}><Icon svg={HelpOutline} inline />Add one or more selections <ToggleSelectionModeButton /></div>
|
||||
<div className='msp-help-description'><Icon svg={HelpOutlineSvg} inline />Add one or more selections (toggle <ToggleSelectionModeButton inline /> mode)</div>
|
||||
</div>}
|
||||
</>;
|
||||
}
|
||||
@@ -180,8 +171,8 @@ export class MeasurementControls extends PurePluginUIComponent<{}, { isBusy: boo
|
||||
render() {
|
||||
return <>
|
||||
<div className='msp-flex-row'>
|
||||
<ToggleButton icon={Add} label='Add' toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.state.isBusy} className='msp-btn-apply-simple' />
|
||||
<ToggleButton icon={Tune} label='' title='Options' toggle={this.toggleOptions} isSelected={this.state.action === 'options'} disabled={this.state.isBusy} style={{ flex: '0 0 40px', padding: 0 }} />
|
||||
<ToggleButton icon={AddSvg} label='Add' toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.state.isBusy} className='msp-btn-apply-simple' />
|
||||
<ToggleButton icon={TuneSvg} label='' title='Options' toggle={this.toggleOptions} isSelected={this.state.action === 'options'} disabled={this.state.isBusy} style={{ flex: '0 0 40px', padding: 0 }} />
|
||||
</div>
|
||||
{this.state.action === 'add' && this.add()}
|
||||
{this.state.action === 'options' && <MeasurementsOptions />}
|
||||
@@ -297,9 +288,9 @@ class MeasurementEntry extends PurePluginUIComponent<{ cell: StructureMeasuremen
|
||||
<button className='msp-form-control msp-control-button-label msp-no-overflow' title='Click to focus. Hover to highlight.' onClick={this.focus} style={{ width: 'auto', textAlign: 'left' }}>
|
||||
<span dangerouslySetInnerHTML={{ __html: this.label }} />
|
||||
</button>
|
||||
<IconButton svg={cell.state.isHidden ? VisibilityOffOutlined : VisibilityOutlined} toggleState={false} small className='msp-form-control' onClick={this.toggleVisibility} flex title={cell.state.isHidden ? 'Show' : 'Hide'} />
|
||||
<IconButton svg={DeleteOutlined} small className='msp-form-control' onClick={this.delete} flex title='Delete' toggleState={false} />
|
||||
<IconButton svg={MoreHoriz} className='msp-form-control' onClick={this.toggleUpdate} flex title='Actions' toggleState={this.state.showUpdate} />
|
||||
<IconButton svg={cell.state.isHidden ? VisibilityOffOutlinedSvg : VisibilityOutlinedSvg} toggleState={false} small className='msp-form-control' onClick={this.toggleVisibility} flex title={cell.state.isHidden ? 'Show' : 'Hide'} />
|
||||
<IconButton svg={DeleteOutlinedSvg} small className='msp-form-control' onClick={this.delete} flex title='Delete' toggleState={false} />
|
||||
<IconButton svg={MoreHorizSvg} className='msp-form-control' onClick={this.toggleUpdate} flex title='Actions' toggleState={this.state.showUpdate} />
|
||||
</div>
|
||||
{this.state.showUpdate && cell.parent && <>
|
||||
<div className='msp-accent-offset'>
|
||||
|
||||
@@ -5,13 +5,6 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import Close from '@material-ui/icons/Close';
|
||||
import CancelOutlined from '@material-ui/icons/CancelOutlined';
|
||||
import Brush from '@material-ui/icons/Brush';
|
||||
import Restore from '@material-ui/icons/Restore';
|
||||
import Remove from '@material-ui/icons/Remove';
|
||||
import SelectAll from '@material-ui/icons/SelectAll';
|
||||
import HelpOutline from '@material-ui/icons/HelpOutline';
|
||||
import * as React from 'react';
|
||||
import { StructureSelectionQueries, StructureSelectionQuery, getNonStandardResidueQueries, getElementQueries, getPolymerAndBranchedEntityQueries } from '../../mol-plugin-state/helpers/structure-selection-query';
|
||||
import { InteractivityManager } from '../../mol-plugin-state/manager/interactivity';
|
||||
@@ -25,13 +18,13 @@ import { PluginUIComponent, PurePluginUIComponent } from '../base';
|
||||
import { ActionMenu } from '../controls/action-menu';
|
||||
import { Button, ControlGroup, IconButton, ToggleButton } from '../controls/common';
|
||||
import { ParameterControls, ParamOnChange, PureSelectControl } from '../controls/parameters';
|
||||
import { Union, Subtract, Intersect, SetSvg as SetSvg, CubeSvg, Icon } from '../controls/icons';
|
||||
import { UnionSvg, SubtractSvg, IntersectSvg, SetSvg, CubeSvg, Icon, SelectionModeSvg, RemoveSvg, RestoreSvg, HelpOutlineSvg, CancelOutlinedSvg, BrushSvg, CloseSvg } from '../controls/icons';
|
||||
import { AddComponentControls } from './components';
|
||||
import Structure from '../../mol-model/structure/structure/structure';
|
||||
import { ViewportHelpContent, HelpGroup, HelpText } from '../viewport/help';
|
||||
|
||||
|
||||
export class ToggleSelectionModeButton extends PurePluginUIComponent {
|
||||
export class ToggleSelectionModeButton extends PurePluginUIComponent<{ inline?: boolean }> {
|
||||
componentDidMount() {
|
||||
this.subscribe(this.plugin.events.canvas3d.settingsUpdated, () => this.forceUpdate());
|
||||
this.subscribe(this.plugin.layout.events.updated, () => this.forceUpdate());
|
||||
@@ -43,7 +36,10 @@ export class ToggleSelectionModeButton extends PurePluginUIComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
return <IconButton svg={SelectAll} onClick={this._toggleSelMode} title={'Toggle Selection Mode'} style={{ background: 'transparent' }} toggleState={this.plugin.selectionMode} />;
|
||||
const style = this.props.inline
|
||||
? { background: 'transparent', width: 'auto', height: 'auto', lineHeight: 'unset' }
|
||||
: { background: 'transparent' };
|
||||
return <IconButton svg={SelectionModeSvg} onClick={this._toggleSelMode} title={'Toggle Selection Mode'} style={style} toggleState={this.plugin.selectionMode} />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,39 +191,39 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str
|
||||
return <>
|
||||
<div className='msp-flex-row' style={{ background: 'none' }}>
|
||||
<PureSelectControl title={`Picking Level for selecting and highlighting`} param={StructureSelectionParams.granularity} name='granularity' value={granularity} onChange={this.setGranuality} isDisabled={this.isDisabled} />
|
||||
<ToggleButton icon={Union} title={`${ActionHeader.get('add')}. Hold shift key to keep menu open.`} toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={Subtract} title={`${ActionHeader.get('remove')}. Hold shift key to keep menu open.`} toggle={this.toggleRemove} isSelected={this.state.action === 'remove'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={Intersect} title={`${ActionHeader.get('intersect')}. Hold shift key to keep menu open.`} toggle={this.toggleIntersect} isSelected={this.state.action === 'intersect'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={UnionSvg} title={`${ActionHeader.get('add')}. Hold shift key to keep menu open.`} toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={SubtractSvg} title={`${ActionHeader.get('remove')}. Hold shift key to keep menu open.`} toggle={this.toggleRemove} isSelected={this.state.action === 'remove'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={IntersectSvg} title={`${ActionHeader.get('intersect')}. Hold shift key to keep menu open.`} toggle={this.toggleIntersect} isSelected={this.state.action === 'intersect'} disabled={this.isDisabled} />
|
||||
<ToggleButton icon={SetSvg} title={`${ActionHeader.get('set')}. Hold shift key to keep menu open.`} toggle={this.toggleSet} isSelected={this.state.action === 'set'} disabled={this.isDisabled} />
|
||||
|
||||
<ToggleButton icon={Brush} title='Color Selection' toggle={this.toggleColor} isSelected={this.state.action === 'color'} disabled={this.isDisabled} style={{ marginLeft: '10px' }} />
|
||||
<ToggleButton icon={BrushSvg} title='Color Selection' toggle={this.toggleColor} isSelected={this.state.action === 'color'} disabled={this.isDisabled} style={{ marginLeft: '10px' }} />
|
||||
<ToggleButton icon={CubeSvg} title='Create Representation of Selection' toggle={this.toggleAddRepr} isSelected={this.state.action === 'add-repr'} disabled={this.isDisabled} />
|
||||
<IconButton svg={Remove} title='Subtract Selection from Representations' onClick={this.subtract} disabled={this.isDisabled} />
|
||||
<IconButton svg={Restore} onClick={this.undo} disabled={!this.state.canUndo || this.isDisabled} title={undoTitle} />
|
||||
<IconButton svg={RemoveSvg} title='Subtract Selection from Representations' onClick={this.subtract} disabled={this.isDisabled} />
|
||||
<IconButton svg={RestoreSvg} onClick={this.undo} disabled={!this.state.canUndo || this.isDisabled} title={undoTitle} />
|
||||
|
||||
<ToggleButton icon={HelpOutline} title='Show/hide help' toggle={this.toggleHelp} style={{ marginLeft: '10px' }} isSelected={this.state.action === 'help'} />
|
||||
<IconButton svg={CancelOutlined} title='Turn selection mode off' onClick={this.turnOff} />
|
||||
<ToggleButton icon={HelpOutlineSvg} title='Show/hide help' toggle={this.toggleHelp} style={{ marginLeft: '10px' }} isSelected={this.state.action === 'help'} />
|
||||
<IconButton svg={CancelOutlinedSvg} title='Turn selection mode off' onClick={this.turnOff} />
|
||||
</div>
|
||||
{(this.state.action && this.state.action !== 'color' && this.state.action !== 'add-repr' && this.state.action !== 'help') && <div className='msp-selection-viewport-controls-actions'>
|
||||
<ActionMenu header={ActionHeader.get(this.state.action as StructureSelectionModifier)} title='Click to close.' items={this.queries} onSelect={this.selectQuery} noOffset />
|
||||
</div>}
|
||||
{this.state.action === 'color' && <div className='msp-selection-viewport-controls-actions'>
|
||||
<ControlGroup header='Color' title='Click to close.' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleColor} topRightIcon={Close}>
|
||||
<ControlGroup header='Color' title='Click to close.' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleColor} topRightIcon={CloseSvg}>
|
||||
<ApplyColorControls onApply={this.toggleColor} />
|
||||
</ControlGroup>
|
||||
</div>}
|
||||
{this.state.action === 'add-repr' && <div className='msp-selection-viewport-controls-actions'>
|
||||
<ControlGroup header='Add Representation' title='Click to close.' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleAddRepr} topRightIcon={Close}>
|
||||
<ControlGroup header='Add Representation' title='Click to close.' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleAddRepr} topRightIcon={CloseSvg}>
|
||||
<AddComponentControls onApply={this.toggleAddRepr} forSelection />
|
||||
</ControlGroup>
|
||||
</div>}
|
||||
{this.state.action === 'help' && <div className='msp-selection-viewport-controls-actions'>
|
||||
<ControlGroup header='Help' title='Click to close.' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleHelp} topRightIcon={Close} maxHeight='300px'>
|
||||
<ControlGroup header='Help' title='Click to close.' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleHelp} topRightIcon={CloseSvg} maxHeight='300px'>
|
||||
<HelpGroup header='Selection Operations'>
|
||||
<HelpText>Use <Icon svg={Union} inline /> <Icon svg={Subtract} inline /> <Icon svg={Intersect} inline /> <Icon svg={SetSvg} inline /> to modify the selection.</HelpText>
|
||||
<HelpText>Use <Icon svg={UnionSvg} inline /> <Icon svg={SubtractSvg} inline /> <Icon svg={IntersectSvg} inline /> <Icon svg={SetSvg} inline /> to modify the selection.</HelpText>
|
||||
</HelpGroup>
|
||||
<HelpGroup header='Representation Operations'>
|
||||
<HelpText>Use <Icon svg={Brush} inline /> <Icon svg={CubeSvg} inline /> <Icon svg={Remove} inline /> <Icon svg={Restore} inline /> to color, create selection/representation, subtract it, or undo actions.</HelpText>
|
||||
<HelpText>Use <Icon svg={BrushSvg} inline /> <Icon svg={CubeSvg} inline /> <Icon svg={RemoveSvg} inline /> <Icon svg={RestoreSvg} inline /> to color, create selection/representation, subtract it, or undo actions.</HelpText>
|
||||
</HelpGroup>
|
||||
<ViewportHelpContent selectOnly={true} />
|
||||
</ControlGroup>
|
||||
@@ -303,7 +299,7 @@ export class StructureSelectionStatsControls extends PluginUIComponent<{ hideOnE
|
||||
style={{ textAlignLast: !empty ? 'left' : void 0 }}>
|
||||
{this.stats}
|
||||
</Button>
|
||||
{!empty && <IconButton svg={CancelOutlined} onClick={this.clear} title='Clear' className='msp-form-control' flex />}
|
||||
{!empty && <IconButton svg={CancelOutlinedSvg} onClick={this.clear} title='Clear' className='msp-form-control' flex />}
|
||||
</div>
|
||||
</>;
|
||||
}
|
||||
@@ -333,7 +329,7 @@ class ApplyColorControls extends PurePluginUIComponent<ApplyColorControlsProps,
|
||||
render() {
|
||||
return <>
|
||||
<ParameterControls params={this.params} values={this.state.values} onChangeValues={this.paramsChanged} />
|
||||
<Button icon={Brush} className='msp-btn-commit msp-btn-commit-on' onClick={this.apply} style={{ marginTop: '1px' }}>
|
||||
<Button icon={BrushSvg} className='msp-btn-commit msp-btn-commit-on' onClick={this.apply} style={{ marginTop: '1px' }}>
|
||||
Apply Coloring
|
||||
</Button>
|
||||
</>;
|
||||
|
||||
@@ -16,8 +16,7 @@ import { StructureFocusControls } from './focus';
|
||||
import { UpdateTransformControl } from '../state/update-transform';
|
||||
import { StructureSelectionStatsControls } from './selection';
|
||||
import { StateSelection } from '../../mol-state';
|
||||
import BookmarksOutlined from '@material-ui/icons/BookmarksOutlined';
|
||||
import { MoleculeSvg } from '../controls/icons';
|
||||
import { MoleculeSvg, BookmarksOutlinedSvg } from '../controls/icons';
|
||||
|
||||
interface StructureSourceControlState extends CollapsableState {
|
||||
isBusy: boolean,
|
||||
@@ -270,7 +269,7 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo
|
||||
return <>
|
||||
<div className='msp-flex-row' style={{ marginTop: '1px' }}>
|
||||
<Button noOverflow flex onClick={this.toggleHierarchy} disabled={disabled} title={label}>{label}</Button>
|
||||
{presets.length > 0 && <IconButton svg={BookmarksOutlined} className='msp-form-control' flex='40px' onClick={this.togglePreset} title='Apply a structure presets to the current hierarchy.' toggleState={this.state.show === 'presets'} disabled={disabled} />}
|
||||
{presets.length > 0 && <IconButton svg={BookmarksOutlinedSvg} className='msp-form-control' flex='40px' onClick={this.togglePreset} title='Apply a structure presets to the current hierarchy.' toggleState={this.state.show === 'presets'} disabled={disabled} />}
|
||||
</div>
|
||||
{this.state.show === 'hierarchy' && <ActionMenu items={this.hierarchyItems} onSelect={this.selectHierarchy} multiselect />}
|
||||
{this.state.show === 'presets' && <ActionMenu items={presets} onSelect={this.applyPreset} />}
|
||||
|
||||
@@ -5,18 +5,10 @@
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import FlipToFrontIcon from '@material-ui/icons/FlipToFront';
|
||||
import HelpOutline from '@material-ui/icons/HelpOutline';
|
||||
import LinearScaleIcon from '@material-ui/icons/LinearScale';
|
||||
import ScatterPlotIcon from '@material-ui/icons/ScatterPlot';
|
||||
import ArrowDownward from '@material-ui/icons/ArrowDownward';
|
||||
import ArrowUpward from '@material-ui/icons/ArrowUpward';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import Tune from '@material-ui/icons/Tune';
|
||||
import { CollapsableControls, PurePluginUIComponent } from '../base';
|
||||
import { Icon } from '../controls/icons';
|
||||
import { Icon, ArrowUpwardSvg, ArrowDownwardSvg, DeleteOutlinedSvg, HelpOutlineSvg, TuneSvg, SuperposeAtomsSvg, SuperposeChainsSvg, SuperpositionSvg } from '../controls/icons';
|
||||
import { Button, ToggleButton, IconButton } from '../controls/common';
|
||||
import { StructureElement, StructureSelection, QueryContext, Structure } from '../../mol-model/structure';
|
||||
import { StructureElement, StructureSelection, QueryContext, Structure, StructureProperties } from '../../mol-model/structure';
|
||||
import { Mat4 } from '../../mol-math/linear-algebra';
|
||||
import { ParamDefinition as PD } from '../../mol-util/param-definition';
|
||||
import { StateObjectRef, StateObjectCell, StateSelection } from '../../mol-state';
|
||||
@@ -35,7 +27,7 @@ export class StructureSuperpositionControls extends CollapsableControls {
|
||||
return {
|
||||
isCollapsed: false,
|
||||
header: 'Superposition',
|
||||
brand: { accent: 'gray' as const, svg: FlipToFrontIcon },
|
||||
brand: { accent: 'gray' as const, svg: SuperpositionSvg },
|
||||
isHidden: true
|
||||
};
|
||||
}
|
||||
@@ -182,8 +174,7 @@ export class SuperpositionControls extends PurePluginUIComponent<{}, Superpositi
|
||||
}
|
||||
|
||||
moveHistory(e: StructureSelectionHistoryEntry, direction: 'up' | 'down') {
|
||||
// TODO take structure grouping into account
|
||||
this.plugin.managers.structure.selection.modifyHistory(e, direction);
|
||||
this.plugin.managers.structure.selection.modifyHistory(e, direction, void 0, true);
|
||||
}
|
||||
|
||||
focusLoci(loci: StructureElement.Loci) {
|
||||
@@ -204,9 +195,9 @@ export class SuperpositionControls extends PurePluginUIComponent<{}, Superpositi
|
||||
<Button noOverflow title='Click to focus. Hover to highlight.' onClick={() => this.focusLoci(e.loci)} style={{ width: 'auto', textAlign: 'left' }} onMouseEnter={() => this.highlight(e.loci)} onMouseLeave={this.plugin.managers.interactivity.lociHighlights.clearHighlights}>
|
||||
{idx}. <span dangerouslySetInnerHTML={{ __html: e.label }} />
|
||||
</Button>
|
||||
{history.length > 1 && <IconButton svg={ArrowUpward} small={true} className='msp-form-control' onClick={() => this.moveHistory(e, 'up')} flex='20px' title={'Move up'} />}
|
||||
{history.length > 1 && <IconButton svg={ArrowDownward} small={true} className='msp-form-control' onClick={() => this.moveHistory(e, 'down')} flex='20px' title={'Move down'} />}
|
||||
<IconButton svg={DeleteOutlined} small={true} className='msp-form-control' onClick={() => this.plugin.managers.structure.selection.modifyHistory(e, 'remove')} flex title={'Remove'} />
|
||||
{history.length > 1 && <IconButton svg={ArrowUpwardSvg} small={true} className='msp-form-control' onClick={() => this.moveHistory(e, 'up')} flex='20px' title={'Move up'} />}
|
||||
{history.length > 1 && <IconButton svg={ArrowDownwardSvg} small={true} className='msp-form-control' onClick={() => this.moveHistory(e, 'down')} flex='20px' title={'Move down'} />}
|
||||
<IconButton svg={DeleteOutlinedSvg} small={true} className='msp-form-control' onClick={() => this.plugin.managers.structure.selection.modifyHistory(e, 'remove')} flex title={'Remove'} />
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -222,18 +213,19 @@ export class SuperpositionControls extends PurePluginUIComponent<{}, Superpositi
|
||||
}
|
||||
|
||||
get chainEntries() {
|
||||
const location = StructureElement.Location.create();
|
||||
const entries: LociEntry[] = [];
|
||||
this.plugin.managers.structure.selection.entries.forEach(({ selection }, ref) => {
|
||||
const cell = StateObjectRef.resolveAndCheck(this.plugin.state.data, ref);
|
||||
if (!cell || StructureElement.Loci.isEmpty(selection)) return;
|
||||
|
||||
// only single chain selections
|
||||
// TODO wrongly assumes unit is equal to chain
|
||||
if (selection.elements.length > 1) return;
|
||||
// only single polymer chain selections
|
||||
const l = StructureElement.Loci.getFirstLocation(selection, location)!;
|
||||
if (selection.elements.length > 1 || StructureProperties.entity.type(l) !== 'polymer') return;
|
||||
|
||||
const stats = StructureElement.Stats.ofLoci(selection);
|
||||
const counts = structureElementStatsLabel(stats, { countsOnly: true });
|
||||
const chain = elementLabel(stats.firstElementLoc, { reverse: true, granularity: 'chain' }).split('|');
|
||||
const chain = elementLabel(l, { reverse: true, granularity: 'chain' }).split('|');
|
||||
const label = `${counts} | ${chain[0]} | ${chain[chain.length - 1]}`;
|
||||
entries.push({ loci: selection, label, cell });
|
||||
});
|
||||
@@ -241,7 +233,6 @@ export class SuperpositionControls extends PurePluginUIComponent<{}, Superpositi
|
||||
}
|
||||
|
||||
get atomEntries() {
|
||||
// TODO have stable order of structureEntries, independent of history order
|
||||
const structureEntries = new Map<Structure, StructureSelectionHistoryEntry[]>();
|
||||
const history = this.plugin.managers.structure.selection.additionsHistory;
|
||||
|
||||
@@ -279,7 +270,7 @@ export class SuperpositionControls extends PurePluginUIComponent<{}, Superpositi
|
||||
{entries.map((e, i) => this.lociEntry(e, i))}
|
||||
</div>}
|
||||
{entries.length < 2 && <div className='msp-control-offset msp-help-text'>
|
||||
<div className='msp-help-description'><Icon svg={HelpOutline} inline />Add 2 or more selections <ToggleSelectionModeButton /> from separate structures. Selections must be limited to single chains or parts of single chains.</div>
|
||||
<div className='msp-help-description'><Icon svg={HelpOutlineSvg} inline />Add 2 or more selections (toggle <ToggleSelectionModeButton inline /> mode) from separate structures. Selections must be limited to single polymer chains or residues therein.</div>
|
||||
</div>}
|
||||
{entries.length > 1 && <Button title='Superpose structures by selected chains.' className='msp-btn-commit msp-btn-commit-on' onClick={this.superposeChains} style={{ marginTop: '1px' }}>
|
||||
Superpose
|
||||
@@ -294,7 +285,7 @@ export class SuperpositionControls extends PurePluginUIComponent<{}, Superpositi
|
||||
{entries.map((e, i) => this.atomsLociEntry(e, i))}
|
||||
</div>}
|
||||
{entries.length < 2 && <div className='msp-control-offset msp-help-text'>
|
||||
<div className='msp-help-description'><Icon svg={HelpOutline} inline />Add 1 or more selections <ToggleSelectionModeButton /> from
|
||||
<div className='msp-help-description'><Icon svg={HelpOutlineSvg} inline />Add 1 or more selections (toggle <ToggleSelectionModeButton inline /> mode) from
|
||||
separate structures. Selections must be limited to single atoms.</div>
|
||||
</div>}
|
||||
{entries.length > 1 && <Button title='Superpose structures by selected atoms.' className='msp-btn-commit msp-btn-commit-on' onClick={this.superposeAtoms} style={{ marginTop: '1px' }}>
|
||||
@@ -310,9 +301,9 @@ export class SuperpositionControls extends PurePluginUIComponent<{}, Superpositi
|
||||
render() {
|
||||
return <>
|
||||
<div className='msp-flex-row'>
|
||||
<ToggleButton icon={LinearScaleIcon} label='By Chains' toggle={this.toggleByChains} isSelected={this.state.action === 'byChains'} disabled={this.state.isBusy} />
|
||||
<ToggleButton icon={ScatterPlotIcon} label='By Atoms' toggle={this.toggleByAtoms} isSelected={this.state.action === 'byAtoms'} disabled={this.state.isBusy} />
|
||||
<ToggleButton icon={Tune} label='' title='Options' toggle={this.toggleOptions} isSelected={this.state.action === 'options'} disabled={this.state.isBusy} style={{ flex: '0 0 40px', padding: 0 }} />
|
||||
<ToggleButton icon={SuperposeChainsSvg} label='By Chains' toggle={this.toggleByChains} isSelected={this.state.action === 'byChains'} disabled={this.state.isBusy} />
|
||||
<ToggleButton icon={SuperposeAtomsSvg} label='By Atoms' toggle={this.toggleByAtoms} isSelected={this.state.action === 'byAtoms'} disabled={this.state.isBusy} />
|
||||
<ToggleButton icon={TuneSvg} label='' title='Options' toggle={this.toggleOptions} isSelected={this.state.action === 'options'} disabled={this.state.isBusy} style={{ flex: '0 0 40px', padding: 0 }} />
|
||||
</div>
|
||||
{this.state.action === 'byChains' && this.addByChains()}
|
||||
{this.state.action === 'byAtoms' && this.addByAtoms()}
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import Add from '@material-ui/icons/Add';
|
||||
import BlurOn from '@material-ui/icons/BlurOn';
|
||||
import Check from '@material-ui/icons/Check';
|
||||
import ErrorSvg from '@material-ui/icons/Error';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import MoreHoriz from '@material-ui/icons/MoreHoriz';
|
||||
import VisibilityOffOutlined from '@material-ui/icons/VisibilityOffOutlined';
|
||||
import VisibilityOutlined from '@material-ui/icons/VisibilityOutlined';
|
||||
import * as React from 'react';
|
||||
import { StructureHierarchyManager } from '../../mol-plugin-state/manager/structure/hierarchy';
|
||||
import { VolumeHierarchyManager } from '../../mol-plugin-state/manager/volume/hierarchy';
|
||||
@@ -28,6 +20,7 @@ import { ApplyActionControl } from '../state/apply-action';
|
||||
import { UpdateTransformControl } from '../state/update-transform';
|
||||
import { BindingsHelp } from '../viewport/help';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
import { BlurOnSvg, ErrorSvg, CheckSvg, AddSvg, VisibilityOffOutlinedSvg, VisibilityOutlinedSvg, DeleteOutlinedSvg, MoreHorizSvg } from '../controls/icons';
|
||||
|
||||
interface VolumeStreamingControlState extends CollapsableState {
|
||||
isBusy: boolean
|
||||
@@ -40,7 +33,7 @@ export class VolumeStreamingControls extends CollapsableControls<{}, VolumeStrea
|
||||
isCollapsed: false,
|
||||
isBusy: false,
|
||||
isHidden: true,
|
||||
brand: { accent: 'cyan', svg: BlurOn }
|
||||
brand: { accent: 'cyan', svg: BlurOnSvg }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -84,7 +77,7 @@ export class VolumeStreamingControls extends CollapsableControls<{}, VolumeStrea
|
||||
? { header: 'Error enabling', icon: ErrorSvg, title: rootCell.errorText }
|
||||
: rootCell && rootCell.obj?.data.entries.length === 0
|
||||
? { header: 'Error enabling', icon: ErrorSvg, title: 'No entry for streaming found' }
|
||||
: { header: 'Enable', icon: Check, title: 'Enable' };
|
||||
: { header: 'Enable', icon: CheckSvg, title: 'Enable' };
|
||||
|
||||
return <ApplyActionControl state={pivot.cell.parent} action={InitVolumeStreaming} initiallyCollapsed={true} nodeRef={pivot.cell.transform.ref} simpleApply={simpleApply} />;
|
||||
}
|
||||
@@ -121,7 +114,7 @@ export class VolumeSourceControls extends CollapsableControls<{}, VolumeSourceCo
|
||||
isCollapsed: false,
|
||||
isBusy: false,
|
||||
isHidden: true,
|
||||
brand: { accent: 'purple', svg: BlurOn }
|
||||
brand: { accent: 'purple', svg: BlurOnSvg }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -199,7 +192,7 @@ export class VolumeSourceControls extends CollapsableControls<{}, VolumeSourceCo
|
||||
return <>
|
||||
<div className='msp-flex-row' style={{ marginTop: '1px' }}>
|
||||
<Button noOverflow flex onClick={this.toggleHierarchy} disabled={disabled} title={label}>{label}</Button>
|
||||
{!this.isEmpty && <IconButton svg={Add} onClick={this.toggleAddRepr} title='Apply a structure presets to the current hierarchy.' toggleState={this.state.show === 'add-repr'} disabled={disabled} />}
|
||||
{!this.isEmpty && <IconButton svg={AddSvg} onClick={this.toggleAddRepr} title='Apply a structure presets to the current hierarchy.' toggleState={this.state.show === 'add-repr'} disabled={disabled} />}
|
||||
</div>
|
||||
{this.state.show === 'hierarchy' && <ActionMenu items={this.hierarchyItems} onSelect={this.selectCurrent} />}
|
||||
{this.state.show === 'add-repr' && <ActionMenu items={this.addActions} onSelect={this.selectAdd} />}
|
||||
@@ -258,9 +251,9 @@ class VolumeRepresentationControls extends PurePluginUIComponent<{ representatio
|
||||
{repr.obj?.label}
|
||||
<small className='msp-25-lower-contrast-text' style={{ float: 'right' }}>{repr.obj?.description}</small>
|
||||
</Button>
|
||||
<IconButton svg={repr.state.isHidden ? VisibilityOffOutlined : VisibilityOutlined} toggleState={false} onClick={this.toggleVisible} title={`${repr.state.isHidden ? 'Show' : 'Hide'} component`} small className='msp-form-control' flex />
|
||||
<IconButton svg={DeleteOutlined} onClick={this.remove} title='Remove' small />
|
||||
<IconButton svg={MoreHoriz} onClick={this.toggleUpdate} title='Actions' toggleState={this.state.action === 'update'} />
|
||||
<IconButton svg={repr.state.isHidden ? VisibilityOffOutlinedSvg : VisibilityOutlinedSvg} toggleState={false} onClick={this.toggleVisible} title={`${repr.state.isHidden ? 'Show' : 'Hide'} component`} small className='msp-form-control' flex />
|
||||
<IconButton svg={DeleteOutlinedSvg} onClick={this.remove} title='Remove' small />
|
||||
<IconButton svg={MoreHorizSvg} onClick={this.toggleUpdate} title='Actions' toggleState={this.state.action === 'update'} />
|
||||
</div>
|
||||
{this.state.action === 'update' && !!repr.parent && <div style={{ marginBottom: '6px' }} className='msp-accent-offset'>
|
||||
<UpdateTransformControl state={repr.parent} transform={repr.transform} customHeader='none' noMargin />
|
||||
|
||||
@@ -11,7 +11,7 @@ import { TaskManager } from '../mol-plugin/util/task-manager';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { Progress } from '../mol-task';
|
||||
import { IconButton } from './controls/common';
|
||||
import Cancel from '@material-ui/icons/Cancel';
|
||||
import { CancelSvg } from './controls/icons';
|
||||
|
||||
export class BackgroundTaskProgress extends PluginUIComponent<{ }, { tracked: OrderedMap<number, TaskManager.ProgressEvent> }> {
|
||||
componentDidMount() {
|
||||
@@ -49,7 +49,7 @@ class ProgressEntry extends PluginUIComponent<{ event: TaskManager.ProgressEvent
|
||||
|
||||
return <div className='msp-task-state'>
|
||||
<div>
|
||||
{root.progress.canAbort && <IconButton svg={Cancel} onClick={this.abort} title='Abort' />}
|
||||
{root.progress.canAbort && <IconButton svg={CancelSvg} onClick={this.abort} title='Abort' />}
|
||||
<div>
|
||||
{root.progress.message} {pr} {subtasks}
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ import * as React from 'react';
|
||||
import { PluginUIComponent } from './base';
|
||||
import { PluginToastManager } from '../mol-plugin/util/toast';
|
||||
import { IconButton } from './controls/common';
|
||||
import Cancel from '@material-ui/icons/Cancel';
|
||||
import { CancelSvg } from './controls/icons';
|
||||
|
||||
class ToastEntry extends PluginUIComponent<{ entry: PluginToastManager.Entry }> {
|
||||
private hide = () => {
|
||||
@@ -33,7 +33,7 @@ class ToastEntry extends PluginUIComponent<{ entry: PluginToastManager.Entry }>
|
||||
</div>
|
||||
<div className='msp-toast-clear'></div>
|
||||
<div className='msp-toast-hide'>
|
||||
<IconButton svg={Cancel} onClick={this.hide} title='Hide' className='msp-no-hover-outline' />
|
||||
<IconButton svg={CancelSvg} onClick={this.hide} title='Hide' className='msp-no-hover-outline' />
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,6 @@
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
import Autorenew from '@material-ui/icons/Autorenew';
|
||||
import BuildOutlined from '@material-ui/icons/BuildOutlined';
|
||||
import CameraOutlined from '@material-ui/icons/CameraOutlined';
|
||||
import Close from '@material-ui/icons/Close';
|
||||
import Fullscreen from '@material-ui/icons/Fullscreen';
|
||||
import Tune from '@material-ui/icons/Tune';
|
||||
import * as React from 'react';
|
||||
import { Subject } from 'rxjs';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
@@ -23,6 +17,7 @@ import { ControlGroup, IconButton } from './controls/common';
|
||||
import { ToggleSelectionModeButton } from './structure/selection';
|
||||
import { DownloadScreenshotControls } from './viewport/screenshot';
|
||||
import { SimpleSettingsControl } from './viewport/simple-settings';
|
||||
import { AutorenewSvg, CameraOutlinedSvg, BuildOutlinedSvg, FullscreenSvg, TuneSvg, CloseSvg } from './controls/icons';
|
||||
|
||||
interface ViewportControlsState {
|
||||
isSettingsExpanded: boolean,
|
||||
@@ -93,17 +88,17 @@ export class ViewportControls extends PluginUIComponent<ViewportControlsProps, V
|
||||
<div className='msp-viewport-controls-buttons'>
|
||||
<div>
|
||||
<div className='msp-semi-transparent-background' />
|
||||
{this.icon(Autorenew, this.resetCamera, 'Reset Camera')}
|
||||
{this.icon(AutorenewSvg, this.resetCamera, 'Reset Camera')}
|
||||
</div>
|
||||
<div>
|
||||
<div className='msp-semi-transparent-background' />
|
||||
{this.icon(CameraOutlined, this.toggleScreenshotExpanded, 'Screenshot / State Snapshot', this.state.isScreenshotExpanded)}
|
||||
{this.icon(CameraOutlinedSvg, this.toggleScreenshotExpanded, 'Screenshot / State Snapshot', this.state.isScreenshotExpanded)}
|
||||
</div>
|
||||
<div>
|
||||
<div className='msp-semi-transparent-background' />
|
||||
{this.icon(BuildOutlined, this.toggleControls, 'Toggle Controls Panel', this.plugin.layout.state.showControls)}
|
||||
{this.plugin.config.get(PluginConfig.Viewport.ShowExpand) && this.icon(Fullscreen, this.toggleExpanded, 'Toggle Expanded Viewport', this.plugin.layout.state.isExpanded)}
|
||||
{this.icon(Tune, this.toggleSettingsExpanded, 'Settings / Controls Info', this.state.isSettingsExpanded)}
|
||||
{this.icon(BuildOutlinedSvg, this.toggleControls, 'Toggle Controls Panel', this.plugin.layout.state.showControls)}
|
||||
{this.plugin.config.get(PluginConfig.Viewport.ShowExpand) && this.icon(FullscreenSvg, this.toggleExpanded, 'Toggle Expanded Viewport', this.plugin.layout.state.isExpanded)}
|
||||
{this.icon(TuneSvg, this.toggleSettingsExpanded, 'Settings / Controls Info', this.state.isSettingsExpanded)}
|
||||
</div>
|
||||
{this.plugin.config.get(PluginConfig.Viewport.ShowSelectionMode) && <div>
|
||||
<div className='msp-semi-transparent-background' />
|
||||
@@ -112,13 +107,13 @@ export class ViewportControls extends PluginUIComponent<ViewportControlsProps, V
|
||||
</div>
|
||||
{this.state.isScreenshotExpanded && <div className='msp-viewport-controls-panel'>
|
||||
<ControlGroup header='Screenshot / State' title='Click to close.' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleScreenshotExpanded}
|
||||
topRightIcon={Close} noTopMargin childrenClassName='msp-viewport-controls-panel-controls'>
|
||||
topRightIcon={CloseSvg} noTopMargin childrenClassName='msp-viewport-controls-panel-controls'>
|
||||
<DownloadScreenshotControls close={this.toggleScreenshotExpanded} />
|
||||
</ControlGroup>
|
||||
</div>}
|
||||
{this.state.isSettingsExpanded && <div className='msp-viewport-controls-panel'>
|
||||
<ControlGroup header='Settings / Controls Info' title='Click to close.' initialExpanded={true} hideExpander={true} hideOffset={true} onHeaderClick={this.toggleSettingsExpanded}
|
||||
topRightIcon={Close} noTopMargin childrenClassName='msp-viewport-controls-panel-controls'>
|
||||
topRightIcon={CloseSvg} noTopMargin childrenClassName='msp-viewport-controls-panel-controls'>
|
||||
<SimpleSettingsControl />
|
||||
</ControlGroup>
|
||||
</div>}
|
||||
|
||||
@@ -10,11 +10,8 @@ import { PluginUIComponent } from '../base';
|
||||
import { StateTransformer, StateSelection } from '../../mol-state';
|
||||
import { SelectLoci } from '../../mol-plugin/behavior/dynamic/representation';
|
||||
import { FocusLoci } from '../../mol-plugin/behavior/dynamic/representation';
|
||||
import { Icon } from '../controls/icons';
|
||||
import { Icon, ArrowDropDownSvg, ArrowRightSvg, CameraSvg } from '../controls/icons';
|
||||
import { Button } from '../controls/common';
|
||||
import ArrowRight from '@material-ui/icons/ArrowRight';
|
||||
import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
|
||||
import Camera from '@material-ui/icons/Camera';
|
||||
|
||||
function getBindingsList(bindings: { [k: string]: Binding }) {
|
||||
return Object.keys(bindings).map(k => [k, bindings[k]] as [string, Binding]);
|
||||
@@ -60,7 +57,7 @@ export class HelpGroup extends React.PureComponent<{ header: string, initiallyEx
|
||||
return <div className='msp-control-group-wrapper'>
|
||||
<div className='msp-control-group-header'>
|
||||
<Button onClick={this.toggleExpanded}>
|
||||
<Icon svg={this.state.isExpanded ? ArrowDropDown : ArrowRight} />
|
||||
<Icon svg={this.state.isExpanded ? ArrowDropDownSvg : ArrowRightSvg} />
|
||||
{this.props.header}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -155,7 +152,7 @@ export class HelpContent extends PluginUIComponent {
|
||||
<HelpSection header='How-to Guides' />
|
||||
<HelpGroup header='Create an Image'>
|
||||
<HelpText>
|
||||
<p>Use the <Icon svg={Camera} /> icon in the viewport to bring up the screenshot controls.</p>
|
||||
<p>Use the <Icon svg={CameraSvg} /> icon in the viewport to bring up the screenshot controls.</p>
|
||||
<p>To adjust the size of the image, use the <i>Resolution</i> dropdown.</p>
|
||||
</HelpText>
|
||||
</HelpGroup>
|
||||
|
||||
@@ -14,10 +14,9 @@ import { Subject } from 'rxjs';
|
||||
import { ViewportScreenshotHelper } from '../../mol-plugin/util/viewport-screenshot';
|
||||
import { Button, ExpandGroup } from '../controls/common';
|
||||
import { CameraHelperProps } from '../../mol-canvas3d/helper/camera-helper';
|
||||
import GetApp from '@material-ui/icons/GetApp';
|
||||
import Launch from '@material-ui/icons/Launch';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
import { StateExportImportControls, LocalStateSnapshotParams } from '../state/snapshots';
|
||||
import { GetAppSvg, LaunchSvg } from '../controls/icons';
|
||||
|
||||
interface ImageControlsState {
|
||||
showPreview: boolean
|
||||
@@ -141,8 +140,8 @@ export class DownloadScreenshotControls extends PluginUIComponent<{ close: () =>
|
||||
<span>Right-click the image to Copy.</span>
|
||||
</div>
|
||||
<div className='msp-flex-row'>
|
||||
<Button icon={GetApp} onClick={this.download} disabled={this.state.isDisabled}>Download</Button>
|
||||
<Button icon={Launch} onClick={this.openTab} disabled={this.state.isDisabled}>Open in new Tab</Button>
|
||||
<Button icon={GetAppSvg} onClick={this.download} disabled={this.state.isDisabled}>Download</Button>
|
||||
<Button icon={LaunchSvg} onClick={this.openTab} disabled={this.state.isDisabled}>Open in new Tab</Button>
|
||||
</div>
|
||||
<ParameterControls params={this.plugin.helpers.viewportScreenshot!.params} values={this.plugin.helpers.viewportScreenshot!.values} onChange={this.setProps} isDisabled={this.state.isDisabled} />
|
||||
<ExpandGroup header='State'>
|
||||
|
||||
@@ -137,6 +137,11 @@ export class PluginContext {
|
||||
return this.state.data.build();
|
||||
}
|
||||
|
||||
readonly helpers = {
|
||||
substructureParent: new SubstructureParentHelper(this),
|
||||
viewportScreenshot: void 0 as ViewportScreenshotHelper | undefined
|
||||
} as const;
|
||||
|
||||
readonly managers = {
|
||||
structure: {
|
||||
hierarchy: new StructureHierarchyManager(this),
|
||||
@@ -164,11 +169,6 @@ export class PluginContext {
|
||||
readonly customStructureControls = new Map<string, { new(): PluginUIComponent<any, any, any> }>();
|
||||
readonly genericRepresentationControls = new Map<string, (selection: StructureHierarchyManager['selection']) => [StructureHierarchyRef[], string]>();
|
||||
|
||||
readonly helpers = {
|
||||
substructureParent: new SubstructureParentHelper(this),
|
||||
viewportScreenshot: void 0 as ViewportScreenshotHelper | undefined
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Used to store application specific custom state which is then available
|
||||
* to State Actions and similar constructs via the PluginContext.
|
||||
@@ -243,6 +243,7 @@ export class PluginContext {
|
||||
this.state.dispose();
|
||||
this.tasks.dispose();
|
||||
this.layout.dispose();
|
||||
this.helpers.substructureParent.dispose();
|
||||
|
||||
objectForEach(this.managers, m => (m as any)?.dispose?.());
|
||||
objectForEach(this.managers.structure, m => (m as any)?.dispose?.());
|
||||
|
||||
@@ -8,10 +8,18 @@ import { Structure } from '../../mol-model/structure';
|
||||
import { PluginStateObject } from '../../mol-plugin-state/objects';
|
||||
import { State, StateObject, StateObjectCell, StateSelection } from '../../mol-state';
|
||||
import { PluginContext } from '../context';
|
||||
import { RxEventHelper } from '../../mol-util/rx-event-helper';
|
||||
|
||||
export { SubstructureParentHelper };
|
||||
|
||||
class SubstructureParentHelper {
|
||||
private ev = RxEventHelper.create();
|
||||
|
||||
readonly events = {
|
||||
updated: this.ev<{ ref: string, oldObj: PluginStateObject.Molecule.Structure | undefined, obj: PluginStateObject.Molecule.Structure }>(),
|
||||
removed: this.ev<{ ref: string, obj: PluginStateObject.Molecule.Structure | undefined }>(),
|
||||
}
|
||||
|
||||
// private decorators = new Map<string, string[]>();
|
||||
private root = new Map<Structure, { ref: string, count: number }>();
|
||||
private tracked = new Map<string, Structure>();
|
||||
@@ -36,7 +44,7 @@ class SubstructureParentHelper {
|
||||
}
|
||||
|
||||
private addMapping(state: State, ref: string, obj: StateObject) {
|
||||
if (!PluginStateObject.Molecule.Structure.is(obj)) return;
|
||||
if (!PluginStateObject.Molecule.Structure.is(obj)) return false;
|
||||
|
||||
this.tracked.set(ref, obj.data);
|
||||
|
||||
@@ -53,10 +61,11 @@ class SubstructureParentHelper {
|
||||
this.root.set(obj.data, { ref: parent.transform.ref, count: 1 });
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private removeMapping(ref: string) {
|
||||
if (!this.tracked.has(ref)) return;
|
||||
if (!this.tracked.has(ref)) return false;
|
||||
|
||||
const s = this.tracked.get(ref)!;
|
||||
this.tracked.delete(ref);
|
||||
@@ -68,13 +77,19 @@ class SubstructureParentHelper {
|
||||
} else {
|
||||
this.root.delete(s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private updateMapping(state: State, ref: string, oldObj: StateObject | undefined, obj: StateObject) {
|
||||
if (!PluginStateObject.Molecule.Structure.is(obj)) return;
|
||||
if (!PluginStateObject.Molecule.Structure.is(obj)) return false;
|
||||
|
||||
this.removeMapping(ref);
|
||||
this.addMapping(state, ref, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.ev.dispose();
|
||||
}
|
||||
|
||||
constructor(private plugin: PluginContext) {
|
||||
@@ -83,11 +98,15 @@ class SubstructureParentHelper {
|
||||
});
|
||||
|
||||
plugin.state.data.events.object.removed.subscribe(e => {
|
||||
this.removeMapping(e.ref);
|
||||
if (this.removeMapping(e.ref)) {
|
||||
this.events.removed.next({ ref: e.ref, obj: e.obj });
|
||||
}
|
||||
});
|
||||
|
||||
plugin.state.data.events.object.updated.subscribe(e => {
|
||||
this.updateMapping(e.state, e.ref, e.oldObj, e.obj);
|
||||
if (this.updateMapping(e.state, e.ref, e.oldObj, e.obj)) {
|
||||
this.events.updated.next({ ref: e.ref, oldObj: e.oldObj, obj: e.obj });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ interface ComplexVisualBuilder<P extends StructureParams, G extends Geometry> {
|
||||
createGeometry(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<P>, geometry?: G): Promise<G> | G
|
||||
createLocationIterator(structure: Structure): LocationIterator
|
||||
getLoci(pickingId: PickingId, structure: Structure, id: number): Loci
|
||||
eachLocation(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean): boolean,
|
||||
eachLocation(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean, isMarking: boolean): boolean,
|
||||
setUpdateState(state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructure: Structure, currentStructure: Structure): void
|
||||
}
|
||||
|
||||
@@ -173,11 +173,11 @@ export function ComplexVisual<G extends Geometry, P extends StructureParams & Ge
|
||||
return false;
|
||||
}
|
||||
|
||||
function lociApply(loci: Loci, apply: (interval: Interval) => boolean) {
|
||||
function lociApply(loci: Loci, apply: (interval: Interval) => boolean, isMarking: boolean) {
|
||||
if (lociIsSuperset(loci)) {
|
||||
return apply(Interval.ofBounds(0, locationIt.groupCount * locationIt.instanceCount));
|
||||
} else {
|
||||
return eachLocation(loci, currentStructure, apply);
|
||||
return eachLocation(loci, currentStructure, apply, isMarking);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
|
||||
if (!_structure && !structure) {
|
||||
throw new Error('missing structure');
|
||||
} else if (structure && !_structure) {
|
||||
// console.log(label, 'initial structure')
|
||||
// console.log(label, 'initial structure');
|
||||
// First call with a structure, create visuals for each group.
|
||||
_groups = structure.unitSymmetryGroups;
|
||||
for (let i = 0; i < _groups.length; i++) {
|
||||
@@ -75,7 +75,7 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
|
||||
const group = _groups[i];
|
||||
const visualGroup = oldVisuals.get(group.hashCode);
|
||||
if (visualGroup) {
|
||||
// console.log(label, 'found visualGroup to reuse')
|
||||
// console.log(label, 'found visualGroup to reuse');
|
||||
// console.log('old', visualGroup.group)
|
||||
// console.log('new', group)
|
||||
const { visual } = visualGroup;
|
||||
@@ -91,7 +91,7 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
|
||||
applyMarkerAction(arr, Interval.ofBounds(0, arr.length), MarkerAction.RemoveHighlight);
|
||||
}
|
||||
} else {
|
||||
// console.log(label, 'did not find visualGroup to reuse, creating new')
|
||||
// console.log(label, 'did not find visualGroup to reuse, creating new');
|
||||
// newGroups.push(group)
|
||||
const visual = visualCtor(materialId);
|
||||
const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure });
|
||||
@@ -118,7 +118,7 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
|
||||
// })
|
||||
// unusedVisuals.forEach(visual => visual.destroy())
|
||||
} else if (structure && structure !== _structure && Structure.areEquivalent(structure, _structure)) {
|
||||
// console.log(label, 'structures equivalent but not identical')
|
||||
// console.log(label, 'structures equivalent but not identical');
|
||||
// Expects that for structures with the same hashCode,
|
||||
// the unitSymmetryGroups are the same as well.
|
||||
// Re-uses existing visuals for the groups of the new structure.
|
||||
@@ -132,14 +132,13 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct
|
||||
const promise = visualGroup.visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure });
|
||||
if (promise) await promise;
|
||||
visualGroup.group = group;
|
||||
|
||||
} else {
|
||||
throw new Error(`expected to find visual for hashCode ${group.hashCode}`);
|
||||
}
|
||||
if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: _groups.length });
|
||||
}
|
||||
} else {
|
||||
// console.log(label, 'no new structure')
|
||||
// console.log(label, 'no new structure');
|
||||
// No new structure given, just update all visuals with new props.
|
||||
const visualsList: [ UnitsVisual<P>, Unit.SymmetryGroup ][] = []; // TODO avoid allocation
|
||||
visuals.forEach(({ visual, group }) => visualsList.push([ visual, group ]));
|
||||
|
||||
@@ -54,7 +54,7 @@ interface UnitsVisualBuilder<P extends StructureParams, G extends Geometry> {
|
||||
createGeometry(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<P>, geometry?: G): Promise<G> | G
|
||||
createLocationIterator(structureGroup: StructureGroup): LocationIterator
|
||||
getLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number): Loci
|
||||
eachLocation(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean): boolean
|
||||
eachLocation(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean, isMarking: boolean): boolean
|
||||
setUpdateState(state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup): void
|
||||
}
|
||||
|
||||
@@ -224,11 +224,11 @@ export function UnitsVisual<G extends Geometry, P extends StructureParams & Geom
|
||||
return false;
|
||||
}
|
||||
|
||||
function lociApply(loci: Loci, apply: (interval: Interval) => boolean) {
|
||||
function lociApply(loci: Loci, apply: (interval: Interval) => boolean, isMarking: boolean) {
|
||||
if (lociIsSuperset(loci)) {
|
||||
return apply(Interval.ofBounds(0, locationIt.groupCount * locationIt.instanceCount));
|
||||
} else {
|
||||
return eachLocation(loci, currentStructureGroup, apply);
|
||||
return eachLocation(loci, currentStructureGroup, apply, isMarking);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ function getBondLoci(pickingId: PickingId, structure: Structure, id: number) {
|
||||
return EmptyLoci;
|
||||
}
|
||||
|
||||
function eachBond(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) {
|
||||
function eachBond(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean, isMarking: boolean) {
|
||||
let changed = false;
|
||||
if (Bond.isLoci(loci)) {
|
||||
if (!Structure.areEquivalent(loci.structure, structure)) return false;
|
||||
@@ -181,7 +181,7 @@ function eachBond(loci: Loci, structure: Structure, apply: (interval: Interval)
|
||||
OrderedSet.forEach(e.indices, v => {
|
||||
if (!b.connectedIndices.includes(v)) return;
|
||||
b.getEdges(v).forEach(bi => {
|
||||
if (OrderedSet.has(otherLociIndices, bi.indexB)) {
|
||||
if (!isMarking || OrderedSet.has(otherLociIndices, bi.indexB)) {
|
||||
const idx = structure.interUnitBonds.getEdgeIndex(v, unit, bi.indexB, b.unitB);
|
||||
if (apply(Interval.ofSingleton(idx))) changed = true;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ function getBondLoci(pickingId: PickingId, structureGroup: StructureGroup, id: n
|
||||
return EmptyLoci;
|
||||
}
|
||||
|
||||
function eachBond(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) {
|
||||
function eachBond(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean, isMarking: boolean) {
|
||||
let changed = false;
|
||||
if (Bond.isLoci(loci)) {
|
||||
const { structure, group } = structureGroup;
|
||||
@@ -183,7 +183,7 @@ function eachBond(loci: Loci, structureGroup: StructureGroup, apply: (interval:
|
||||
const { offset, b } = unit.bonds;
|
||||
OrderedSet.forEach(e.indices, v => {
|
||||
for (let t = offset[v], _t = offset[v + 1]; t < _t; t++) {
|
||||
if (OrderedSet.has(e.indices, b[t])) {
|
||||
if (!isMarking || OrderedSet.has(e.indices, b[t])) {
|
||||
if (apply(Interval.ofSingleton(unitIdx * groupCount + t))) changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ interface Visual<D, P extends PD.Params> {
|
||||
destroy: () => void
|
||||
}
|
||||
namespace Visual {
|
||||
export type LociApply = (loci: Loci, apply: (interval: Interval) => boolean) => boolean
|
||||
export type LociApply = (loci: Loci, apply: (interval: Interval) => boolean, isMarking: boolean) => boolean
|
||||
|
||||
export function setVisibility(renderObject: GraphicsRenderObject | undefined, visible: boolean) {
|
||||
if (renderObject) renderObject.state.visible = visible;
|
||||
@@ -70,7 +70,7 @@ namespace Visual {
|
||||
if (isEveryLoci(loci)) {
|
||||
changed = applyMarkerAction(array, Interval.ofLength(count), action);
|
||||
} else if (!isEmptyLoci(loci)) {
|
||||
changed = lociApply(loci, interval => applyMarkerAction(array, interval, action));
|
||||
changed = lociApply(loci, interval => applyMarkerAction(array, interval, action), true);
|
||||
}
|
||||
if (changed) ValueCell.update(tMarker, tMarker.ref.value);
|
||||
return changed;
|
||||
@@ -98,7 +98,7 @@ namespace Visual {
|
||||
? clearOverpaint(array, start, end)
|
||||
: applyOverpaintColor(array, start, end, color, overpaint.alpha);
|
||||
};
|
||||
lociApply(loci, apply);
|
||||
lociApply(loci, apply, false);
|
||||
}
|
||||
ValueCell.update(tOverpaint, tOverpaint.ref.value);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ namespace Visual {
|
||||
const end = Interval.end(interval);
|
||||
return applyTransparencyValue(array, start, end, value);
|
||||
};
|
||||
lociApply(loci, apply);
|
||||
lociApply(loci, apply, false);
|
||||
|
||||
ValueCell.update(tTransparency, tTransparency.ref.value);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
@@ -16,13 +16,12 @@ let isProductionMode = process.env.NODE_ENV === 'production';
|
||||
*/
|
||||
let isDebugMode = process.env.DEBUG === '*' || process.env.DEBUG === 'molstar';
|
||||
|
||||
if (typeof window !== 'undefined' && !(window as any).setMolStarDebugMode) {
|
||||
try {
|
||||
(window as any).setMolStarDebugMode = function setMolStarDebugMode(isDebug?: boolean, isProduction?: boolean) {
|
||||
if (typeof isDebug !== 'undefined') isDebugMode = isDebug;
|
||||
if (typeof isProduction !== 'undefined') isProductionMode = isProduction;
|
||||
};
|
||||
} catch { }
|
||||
export { isProductionMode, isDebugMode };
|
||||
|
||||
export function setProductionMode(value?: boolean) {
|
||||
if (typeof value !== 'undefined') isProductionMode = value;
|
||||
}
|
||||
|
||||
export { isProductionMode, isDebugMode };
|
||||
export function setDebugMode(value?: boolean) {
|
||||
if (typeof value !== 'undefined') isDebugMode = value;
|
||||
}
|
||||
@@ -3,7 +3,6 @@ const webpack = require('webpack');
|
||||
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const VersionFile = require('webpack-version-file-plugin');
|
||||
// const CircularDependencyPlugin = require('circular-dependency-plugin');
|
||||
|
||||
const sharedConfig = {
|
||||
module: {
|
||||
@@ -20,18 +19,12 @@ const sharedConfig = {
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
{ loader: 'css-loader', options: { sourceMap: false } },
|
||||
{ loader: 'resolve-url-loader', options: { sourceMap: false } },
|
||||
{ loader: 'sass-loader', options: { sourceMap: false } },
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
// new CircularDependencyPlugin({
|
||||
// include: [ path.resolve(__dirname, 'lib/') ],
|
||||
// failOnError: false,
|
||||
// cwd: process.cwd(),
|
||||
// }),
|
||||
new ExtraWatchWebpackPlugin({
|
||||
files: [
|
||||
'./lib/**/*.scss',
|
||||
@@ -39,8 +32,6 @@ const sharedConfig = {
|
||||
],
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
// __VERSION__: webpack.DefinePlugin.runtimeValue(() => JSON.stringify(require('./package.json').version), true),
|
||||
// __VERSION_TIMESTAMP__: webpack.DefinePlugin.runtimeValue(() => `${new Date().valueOf()}`, true),
|
||||
'process.env.DEBUG': JSON.stringify(process.env.DEBUG)
|
||||
}),
|
||||
new MiniCssExtractPlugin({ filename: 'molstar.css', }),
|
||||
|
||||
Reference in New Issue
Block a user