Skip to content
Snippets Groups Projects
Commit d1d02a18 authored by David Sehnal's avatar David Sehnal
Browse files

mol-plugin: wip

parent fdbb1fa4
No related branches found
No related tags found
No related merge requests found
Showing with 111 additions and 88 deletions
......@@ -5,8 +5,8 @@
*/
export * from './behavior/behavior'
import * as Data from './behavior/data'
import * as Representation from './behavior/representation'
import * as Data from './behavior/built-in/data'
import * as Representation from './behavior/built-in/representation'
export const PluginBehaviors = {
Data,
......
......@@ -4,8 +4,7 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { PluginStateTransform } from '../state/base';
import { PluginStateObjects as SO } from '../state/objects';
import { PluginStateTransform, PluginStateObject } from '../state/base';
import { Transformer } from 'mol-state';
import { Task } from 'mol-task';
import { PluginContext } from 'mol-plugin/context';
......@@ -23,6 +22,9 @@ interface PluginBehavior<P = unknown> {
}
namespace PluginBehavior {
export class Root extends PluginStateObject.Create({ name: 'Root', shortName: 'R', typeClass: 'Root', description: 'Where everything begins.' }) { }
export class Behavior extends PluginStateObject.CreateBehavior<PluginBehavior>({ name: 'Behavior', shortName: 'B', description: 'Modifies plugin functionality.' }) { }
export interface Ctor<P = undefined> { new(ctx: PluginContext, params?: P): PluginBehavior<P> }
export interface CreateParams<P> {
......@@ -30,19 +32,19 @@ namespace PluginBehavior {
ctor: Ctor<P>,
label?: (params: P) => { label: string, description?: string },
display: { name: string, description?: string },
params?: Transformer.Definition<SO.BehaviorRoot, SO.Behavior, P>['params']
params?: Transformer.Definition<Root, Behavior, P>['params']
}
export function create<P>(params: CreateParams<P>) {
return PluginStateTransform.Create<SO.BehaviorRoot, SO.Behavior, P>({
return PluginStateTransform.Create<Root, Behavior, P>({
name: params.name,
display: params.display,
from: [SO.BehaviorRoot],
to: [SO.Behavior],
from: [Root],
to: [Behavior],
params: params.params,
apply({ params: p }, ctx: PluginContext) {
const label = params.label ? params.label(p) : { label: params.display.name, description: params.display.description };
return new SO.Behavior(label, new params.ctor(ctx, p));
return new Behavior(label, new params.ctor(ctx, p));
},
update({ b, newParams }) {
return Task.create('Update Behavior', async () => {
......
......@@ -4,7 +4,7 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { PluginBehavior } from './behavior';
import { PluginBehavior } from '../behavior';
import { PluginCommands } from 'mol-plugin/command';
import { StateTree } from 'mol-state';
......
......@@ -4,38 +4,36 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { PluginBehavior } from './behavior';
import { PluginStateObjects as SO } from '../state/objects';
import { PluginBehavior } from '../behavior';
import { PluginStateObject as SO } from '../../state/base';
class _AddRepresentationToCanvas extends PluginBehavior.Handler {
register(): void {
this.subscribeObservable(this.ctx.events.state.data.object.created, o => {
if (!SO.StructureRepresentation3D.is(o.obj)) return;
if (!SO.isRepresentation3D(o.obj)) return;
this.ctx.canvas3d.add(o.obj.data);
this.ctx.canvas3d.requestDraw(true);
});
this.subscribeObservable(this.ctx.events.state.data.object.updated, o => {
const oo = o.obj;
if (!SO.StructureRepresentation3D.is(oo)) return;
if (!SO.isRepresentation3D(oo)) return;
this.ctx.canvas3d.add(oo.data);
this.ctx.canvas3d.requestDraw(true);
});
this.subscribeObservable(this.ctx.events.state.data.object.removed, o => {
const oo = o.obj;
console.log('removed', o.ref, oo && oo.type);
if (!SO.StructureRepresentation3D.is(oo)) return;
if (!SO.isRepresentation3D(oo)) return;
this.ctx.canvas3d.remove(oo.data);
console.log('removed from canvas', o.ref);
this.ctx.canvas3d.requestDraw(true);
oo.data.destroy();
});
this.subscribeObservable(this.ctx.events.state.data.object.replaced, o => {
if (o.oldObj && SO.StructureRepresentation3D.is(o.oldObj)) {
if (o.oldObj && SO.isRepresentation3D(o.oldObj)) {
this.ctx.canvas3d.remove(o.oldObj.data);
this.ctx.canvas3d.requestDraw(true);
o.oldObj.data.destroy();
}
if (o.newObj && SO.StructureRepresentation3D.is(o.newObj)) {
if (o.newObj && SO.isRepresentation3D(o.newObj)) {
this.ctx.canvas3d.add(o.newObj.data);
this.ctx.canvas3d.requestDraw(true);
}
......
......@@ -7,6 +7,7 @@
import { StateTree, StateSelection, Transformer, Transform } from 'mol-state';
import { Canvas3D } from 'mol-canvas3d/canvas3d';
import { StateTransforms } from './state/transforms';
import { PluginStateObject as PSO } from './state/base';
import { PluginStateObjects as SO } from './state/objects';
import { RxEventHelper } from 'mol-util/rx-event-helper';
import { PluginState } from './state';
......@@ -77,10 +78,10 @@ export class PluginContext {
async _test_initBehaviours() {
const tree = StateTree.build(this.state.behavior.tree)
.toRoot().apply(PluginBehaviors.Data.SetCurrentObject)
.and().toRoot().apply(PluginBehaviors.Data.Update)
.and().toRoot().apply(PluginBehaviors.Data.RemoveObject)
.and().toRoot().apply(PluginBehaviors.Representation.AddRepresentationToCanvas)
.toRoot().apply(PluginBehaviors.Data.SetCurrentObject, { ref: PluginBehaviors.Data.SetCurrentObject.id })
.and().toRoot().apply(PluginBehaviors.Data.Update, { ref: PluginBehaviors.Data.Update.id })
.and().toRoot().apply(PluginBehaviors.Data.RemoveObject, { ref: PluginBehaviors.Data.RemoveObject.id })
.and().toRoot().apply(PluginBehaviors.Representation.AddRepresentationToCanvas, { ref: PluginBehaviors.Representation.AddRepresentationToCanvas.id })
.getTree();
await this.state.updateBehaviour(tree);
......@@ -121,32 +122,32 @@ export class PluginContext {
private initEvents() {
merge(this.events.state.data.object.created, this.events.state.behavior.object.created).subscribe(o => {
console.log('creating', o.obj.type);
if (!SO.Behavior.is(o.obj)) return;
if (!PSO.isBehavior(o.obj)) return;
o.obj.data.register();
});
merge(this.events.state.data.object.removed, this.events.state.behavior.object.removed).subscribe(o => {
if (!SO.Behavior.is(o.obj)) return;
if (!PSO.isBehavior(o.obj)) return;
o.obj.data.unregister();
});
merge(this.events.state.data.object.replaced, this.events.state.behavior.object.replaced).subscribe(o => {
if (o.oldObj && SO.Behavior.is(o.oldObj)) o.oldObj.data.unregister();
if (o.newObj && SO.Behavior.is(o.newObj)) o.newObj.data.register();
if (o.oldObj && PSO.isBehavior(o.oldObj)) o.oldObj.data.unregister();
if (o.newObj && PSO.isBehavior(o.newObj)) o.newObj.data.register();
});
}
_test_centerView() {
const sel = StateSelection.select(StateSelection.root().subtree().ofType(SO.Structure.type), this.state.data);
const sel = StateSelection.select(StateSelection.root().subtree().ofType(SO.Molecule.Structure.type), this.state.data);
if (!sel.length) return;
const center = (sel[0].obj! as SO.Structure).data.boundary.sphere.center;
const center = (sel[0].obj! as SO.Molecule.Structure).data.boundary.sphere.center;
this.canvas3d.camera.setState({ target: center });
this.canvas3d.requestDraw(true);
}
_test_nextModel() {
const models = StateSelection.select('models', this.state.data)[0].obj as SO.Models;
const models = StateSelection.select('models', this.state.data)[0].obj as SO.Molecule.Models;
const idx = (this.state.data.tree.getValue('structure')!.params as Transformer.Params<typeof StateTransforms.Model.CreateStructureFromModel>).modelIndex;
const newTree = StateTree.updateParams(this.state.data.tree, 'structure', { modelIndex: (idx + 1) % models.data.length });
return this.state.updateData(newTree);
......
......@@ -7,6 +7,7 @@
import { State, StateTree } from 'mol-state';
import { PluginStateObjects as SO } from './state/objects';
import { Camera } from 'mol-canvas3d/camera';
import { PluginBehavior } from './behavior';
export { PluginState }
......@@ -28,15 +29,7 @@ class PluginState {
await this.behavior.setSnapshot(snapshot.behaviour);
await this.data.setSnapshot(snapshot.data);
this.plugin.canvas3d.camera.setState(snapshot.canvas3d.camera);
// TODO: handle camera
// console.log({ old: { ...this.plugin.canvas3d.camera }, new: snapshot.canvas3d.camera });
// CombinedCamera.copy(snapshot.canvas3d.camera, this.plugin.canvas3d.camera);
// CombinedCamera.update(this.plugin.canvas3d.camera);
// this.plugin.canvas3d.center
// console.log({ copied: { ...this.plugin.canvas3d.camera } });
this.plugin.canvas3d.requestDraw(true);
// console.log('updated camera');
}
updateData(tree: StateTree) {
......@@ -52,8 +45,8 @@ class PluginState {
}
constructor(private plugin: import('./context').PluginContext) {
this.data = State.create(new SO.DataRoot({ label: 'Root' }, { }), { globalContext: plugin });
this.behavior = State.create(new SO.BehaviorRoot({ label: 'Root' }, { }), { globalContext: plugin });
this.data = State.create(new SO.Root({ label: 'Root' }, { }), { globalContext: plugin });
this.behavior = State.create(new PluginBehavior.Root({ label: 'Root' }, { }), { globalContext: plugin });
}
}
......
......@@ -5,15 +5,33 @@
*/
import { StateObject, Transformer } from 'mol-state';
import { Representation } from 'mol-repr';
import { PluginBehavior } from 'mol-plugin/behavior/behavior';
export type TypeClass = 'root' | 'data' | 'prop'
export namespace PluginStateObject {
export type TypeClass = 'Root' | 'Group' | 'Data' | 'Object' | 'Representation' | 'Behavior'
export type TypeClass = 'Root' | 'Group' | 'Data' | 'Object' | 'Representation3D' | 'Behavior'
export interface TypeInfo { name: string, shortName: string, description: string, typeClass: TypeClass }
export interface Props { label: string, description?: string }
export const Create = StateObject.factory<TypeInfo, Props>();
export function isRepresentation3D(o?: StateObject): o is StateObject<Props, Representation.Any> {
return !!o && (o.type.info as TypeInfo).typeClass === 'Representation3D';
}
export function isBehavior(o?: StateObject): o is StateObject<Props, PluginBehavior> {
return !!o && (o.type.info as TypeInfo).typeClass === 'Behavior';
}
export function CreateRepresentation3D<T extends Representation.Any>(type: { name: string, shortName: string, description: string }) {
return Create<T>({ ...type, typeClass: 'Representation3D' })
}
export function CreateBehavior<T extends PluginBehavior>(type: { name: string, shortName: string, description: string }) {
return Create<T>({ ...type, typeClass: 'Behavior' })
}
}
export namespace PluginStateTransform {
......
......@@ -8,17 +8,16 @@ import { PluginStateObject } from './base';
import { CifFile } from 'mol-io/reader/cif';
import { Model as _Model, Structure as _Structure } from 'mol-model/structure'
import { StructureRepresentation } from 'mol-repr/structure/index';
import { VolumeRepresentation } from 'mol-repr/volume';
import { VolumeData } from 'mol-model/volume';
const _create = PluginStateObject.Create
const _create = PluginStateObject.Create, _createRepr3D = PluginStateObject.CreateRepresentation3D
namespace PluginStateObjects {
export class DataRoot extends _create({ name: 'Root', shortName: 'R', typeClass: 'Root', description: 'Where everything begins.' }) { }
export class BehaviorRoot extends _create({ name: 'Root', shortName: 'R', typeClass: 'Root', description: 'Where everything begins.' }) { }
export class Root extends _create({ name: 'Root', shortName: 'R', typeClass: 'Root', description: 'Where everything begins.' }) { }
export class Group extends _create({ name: 'Group', shortName: 'G', typeClass: 'Group', description: 'A group on entities.' }) { }
export class Behavior extends _create<import('../behavior').PluginBehavior>({ name: 'Behavior', shortName: 'B', typeClass: 'Behavior', description: 'Modifies plugin functionality.' }) { }
export namespace Data {
export class String extends _create<string>({ name: 'String Data', typeClass: 'Data', shortName: 'S_D', description: 'A string.' }) { }
export class Binary extends _create<Uint8Array>({ name: 'Binary Data', typeClass: 'Data', shortName: 'B_D', description: 'A binary blob.' }) { }
......@@ -31,11 +30,17 @@ namespace PluginStateObjects {
// }>({ name: 'Data', typeClass: 'Data', shortName: 'MD', description: 'Multiple Keyed Data.' }) { }
}
export namespace Molecule {
export class Models extends _create<ReadonlyArray<_Model>>({ name: 'Molecule Model', typeClass: 'Object', shortName: 'M_M', description: 'A model of a molecule.' }) { }
export class Structure extends _create<_Structure>({ name: 'Molecule Structure', typeClass: 'Object', shortName: 'M_S', description: 'A structure of a molecule.' }) { }
export class Representation3D extends _createRepr3D<StructureRepresentation<any>>({ name: 'Molecule Structure 3D Representation', shortName: 'S_R', description: 'A 3D representation of a molecular structure.' }) { }
}
export namespace Volume {
export class Data extends _create<VolumeData>({ name: 'Volume Data', typeClass: 'Object', shortName: 'V_D', description: 'Volume Data.' }) { }
export class Representation3D extends _createRepr3D<VolumeRepresentation<any>>({ name: 'Volume 3D Representation', shortName: 'V_R', description: 'A 3D representation of volumetric data.' }) { }
}
export class StructureRepresentation3D extends _create<StructureRepresentation<any>>({ name: 'Molecule Structure Representation', typeClass: 'Representation', shortName: 'S_R', description: 'A representation of a molecular structure.' }) { }
}
export { PluginStateObjects }
\ No newline at end of file
......@@ -13,13 +13,13 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
export { Download }
namespace Download { export interface Params { url: string, isBinary?: boolean, label?: string } }
const Download = PluginStateTransform.Create<SO.DataRoot, SO.Data.String | SO.Data.Binary, Download.Params>({
const Download = PluginStateTransform.Create<SO.Root, SO.Data.String | SO.Data.Binary, Download.Params>({
name: 'download',
display: {
name: 'Download',
description: 'Download string or binary data from the specified URL'
},
from: [SO.DataRoot],
from: [SO.Root],
to: [SO.Data.String, SO.Data.Binary],
params: {
default: () => ({
......
......@@ -15,14 +15,14 @@ import { Mat4 } from 'mol-math/linear-algebra';
export { ParseModelsFromMmCif }
namespace ParseModelsFromMmCif { export interface Params { blockHeader?: string } }
const ParseModelsFromMmCif = PluginStateTransform.Create<SO.Data.Cif, SO.Models, ParseModelsFromMmCif.Params>({
const ParseModelsFromMmCif = PluginStateTransform.Create<SO.Data.Cif, SO.Molecule.Models, ParseModelsFromMmCif.Params>({
name: 'parse-models-from-mmcif',
display: {
name: 'Models from mmCIF',
description: 'Identify and create all separate models in the specified CIF data block'
},
from: [SO.Data.Cif],
to: [SO.Models],
to: [SO.Molecule.Models],
params: {
default: a => ({ blockHeader: a.data.blocks[0].header }),
controls(a) {
......@@ -41,21 +41,21 @@ const ParseModelsFromMmCif = PluginStateTransform.Create<SO.Data.Cif, SO.Models,
const models = await Model.create(Format.mmCIF(block)).runInContext(ctx);
if (models.length === 0) throw new Error('No models found.');
const label = models.length === 1 ? `${models[0].label}` : `${models[0].label} (${models.length} models)`;
return new SO.Models({ label }, models);
return new SO.Molecule.Models({ label }, models);
});
}
});
export { CreateStructureFromModel }
namespace CreateStructureFromModel { export interface Params { modelIndex: number, transform3d?: Mat4 } }
const CreateStructureFromModel = PluginStateTransform.Create<SO.Models, SO.Structure, CreateStructureFromModel.Params>({
const CreateStructureFromModel = PluginStateTransform.Create<SO.Molecule.Models, SO.Molecule.Structure, CreateStructureFromModel.Params>({
name: 'create-structure-from-model',
display: {
name: 'Structure from Model',
description: 'Create a molecular structure from the specified model.'
},
from: [SO.Models],
to: [SO.Structure],
from: [SO.Molecule.Models],
to: [SO.Molecule.Structure],
params: {
default: () => ({ modelIndex: 0 }),
controls: a => ({ modelIndex: PD.Range('Model Index', 'Model Index', 0, 0, Math.max(0, a.data.length - 1), 1) })
......@@ -65,21 +65,21 @@ const CreateStructureFromModel = PluginStateTransform.Create<SO.Models, SO.Struc
if (params.modelIndex < 0 || params.modelIndex >= a.data.length) throw new Error(`Invalid modelIndex ${params.modelIndex}`);
let s = Structure.ofModel(a.data[params.modelIndex]);
if (params.transform3d) s = Structure.transform(s, params.transform3d);
return new SO.Structure({ label: `Model ${s.models[0].modelNum}`, description: s.elementCount === 1 ? '1 element' : `${s.elementCount} elements` }, s);
return new SO.Molecule.Structure({ label: `Model ${s.models[0].modelNum}`, description: s.elementCount === 1 ? '1 element' : `${s.elementCount} elements` }, s);
}
});
export { CreateStructureAssembly }
namespace CreateStructureAssembly { export interface Params { /** if not specified, use the 1st */ id?: string } }
const CreateStructureAssembly = PluginStateTransform.Create<SO.Structure, SO.Structure, CreateStructureAssembly.Params>({
const CreateStructureAssembly = PluginStateTransform.Create<SO.Molecule.Structure, SO.Molecule.Structure, CreateStructureAssembly.Params>({
name: 'create-structure-assembly',
display: {
name: 'Structure Assembly',
description: 'Create a molecular structure assembly.'
},
from: [SO.Structure],
to: [SO.Structure],
from: [SO.Molecule.Structure],
to: [SO.Molecule.Structure],
params: {
default: () => ({ id: void 0 }),
controls(a) {
......@@ -98,26 +98,26 @@ const CreateStructureAssembly = PluginStateTransform.Create<SO.Structure, SO.Str
if (!asm) throw new Error(`Assembly '${id}' not found`);
const s = await StructureSymmetry.buildAssembly(a.data, id!).runInContext(ctx);
return new SO.Structure({ label: `Assembly ${id}`, description: s.elementCount === 1 ? '1 element' : `${s.elementCount} elements` }, s);
return new SO.Molecule.Structure({ label: `Assembly ${id}`, description: s.elementCount === 1 ? '1 element' : `${s.elementCount} elements` }, s);
})
}
});
export { CreateStructureSelection }
namespace CreateStructureSelection { export interface Params { query: Expression, label?: string } }
const CreateStructureSelection = PluginStateTransform.Create<SO.Structure, SO.Structure, CreateStructureSelection.Params>({
const CreateStructureSelection = PluginStateTransform.Create<SO.Molecule.Structure, SO.Molecule.Structure, CreateStructureSelection.Params>({
name: 'create-structure-selection',
display: {
name: 'Structure Selection',
description: 'Create a molecular structure from the specified model.'
},
from: [SO.Structure],
to: [SO.Structure],
from: [SO.Molecule.Structure],
to: [SO.Molecule.Structure],
apply({ a, params }) {
// TODO: use cache, add "update"
const compiled = compile<StructureSelection>(params.query);
const result = compiled(new QueryContext(a.data));
const s = StructureSelection.unionStructure(result);
return new SO.Structure({ label: `${params.label || 'Selection'}`, description: s.elementCount === 1 ? '1 element' : `${s.elementCount} elements` }, s);
return new SO.Molecule.Structure({ label: `${params.label || 'Selection'}`, description: s.elementCount === 1 ? '1 element' : `${s.elementCount} elements` }, s);
}
});
......@@ -14,16 +14,16 @@ import { PluginContext } from 'mol-plugin/context';
export { CreateStructureRepresentation }
namespace CreateStructureRepresentation { export interface Params { } }
const CreateStructureRepresentation = PluginStateTransform.Create<SO.Structure, SO.StructureRepresentation3D, CreateStructureRepresentation.Params>({
const CreateStructureRepresentation = PluginStateTransform.Create<SO.Molecule.Structure, SO.Molecule.Representation3D, CreateStructureRepresentation.Params>({
name: 'create-structure-representation',
display: { name: 'Create 3D Representation' },
from: [SO.Structure],
to: [SO.StructureRepresentation3D],
from: [SO.Molecule.Structure],
to: [SO.Molecule.Representation3D],
apply({ a, params }, plugin: PluginContext) {
return Task.create('Structure Representation', async ctx => {
const repr = BallAndStickRepresentation(); // CartoonRepresentation();
await repr.createOrUpdate({ webgl: plugin.canvas3d.webgl }, DefaultBallAndStickProps, a.data).runInContext(ctx);
return new SO.StructureRepresentation3D({ label: 'Visual Repr.' }, repr);
return new SO.Molecule.Representation3D({ label: 'Visual Repr.' }, repr);
});
},
update({ a, b }, plugin: PluginContext) {
......
......@@ -11,15 +11,18 @@ import { Viewport } from './viewport';
import { Controls, _test_CreateTransform } from './controls';
import { Transformer } from 'mol-state';
// TODO: base object with subscribe helpers
// TODO: base object with subscribe helpers, separate behavior list etc
export class Plugin extends React.Component<{ plugin: PluginContext }, { }> {
render() {
return <div style={{ position: 'absolute', width: '100%', height: '100%', fontFamily: 'monospace' }}>
<div style={{ position: 'absolute', width: '350px', height: '100%', overflowY: 'scroll' }}>
<StateTree plugin={this.props.plugin} />
<h3>Data</h3>
<StateTree plugin={this.props.plugin} state={this.props.plugin.state.data} />
<hr />
<_test_CurrentObject plugin={this.props.plugin} />
<h3>Behavior</h3>
<StateTree plugin={this.props.plugin} state={this.props.plugin.state.behavior} />
</div>
<div style={{ position: 'absolute', left: '350px', right: '250px', height: '100%' }}>
<Viewport plugin={this.props.plugin} />
......
......@@ -7,46 +7,49 @@
import * as React from 'react';
import { PluginContext } from '../context';
import { PluginStateObject } from 'mol-plugin/state/base';
import { StateObject } from 'mol-state'
import { StateObject, State } from 'mol-state'
import { PluginCommands } from 'mol-plugin/command';
export class StateTree extends React.Component<{ plugin: PluginContext }, { }> {
export class StateTree extends React.Component<{ plugin: PluginContext, state: State }, { }> {
componentDidMount() {
// TODO: move to constructor?
this.props.plugin.events.state.data.updated.subscribe(() => this.forceUpdate());
this.props.state.context.events.updated.subscribe(() => this.forceUpdate());
}
render() {
// const n = this.props.plugin.state.data.tree.nodes.get(this.props.plugin.state.data.tree.rootRef)!;
const n = this.props.plugin.state.data.tree.rootRef;
const n = this.props.state.tree.rootRef;
return <div>
<StateTreeNode plugin={this.props.plugin} nodeRef={n} key={n} />
<StateTreeNode plugin={this.props.plugin} state={this.props.state} nodeRef={n} key={n} />
{ /* n.children.map(c => <StateTreeNode plugin={this.props.plugin} nodeRef={c!} key={c} />) */}
</div>;
}
}
export class StateTreeNode extends React.Component<{ plugin: PluginContext, nodeRef: string }, { }> {
export class StateTreeNode extends React.Component<{ plugin: PluginContext, nodeRef: string, state: State }, { }> {
render() {
const n = this.props.plugin.state.data.tree.nodes.get(this.props.nodeRef)!;
const obj = this.props.plugin.state.data.objects.get(this.props.nodeRef)!;
const n = this.props.state.tree.nodes.get(this.props.nodeRef)!;
const obj = this.props.state.objects.get(this.props.nodeRef)!;
const remove = <>[<a href='#' onClick={e => {
e.preventDefault();
PluginCommands.Data.RemoveObject.dispatch(this.props.plugin, { ref: this.props.nodeRef });
}}>X</a>]</>
if (!obj.obj) {
return <div style={{ borderLeft: '1px solid black', paddingLeft: '5px' }}>
{StateObject.StateType[obj.state]} {obj.errorText}
return <div style={{ borderLeft: '1px solid black', paddingLeft: '7px' }}>
{remove} {StateObject.StateType[obj.state]} {obj.errorText}
</div>;
}
const props = obj.obj!.props as PluginStateObject.Props;
const type = obj.obj!.type.info as PluginStateObject.TypeInfo;
return <div style={{ borderLeft: '1px solid #999', paddingLeft: '7px' }}>
[<a href='#' onClick={e => {
e.preventDefault();
PluginCommands.Data.RemoveObject.dispatch(this.props.plugin, { ref: this.props.nodeRef });
}}>X</a>][<span title={type.description}>{ type.shortName }</span>] <a href='#' onClick={e => {
return <div style={{ borderLeft: '0px solid #999', paddingLeft: '0px' }}>
{remove}[<span title={type.description}>{ type.shortName }</span>] <a href='#' onClick={e => {
e.preventDefault();
PluginCommands.Data.SetCurrentObject.dispatch(this.props.plugin, { ref: this.props.nodeRef });
}}>{props.label}</a> {props.description ? <small>{props.description}</small> : void 0}
{n.children.size === 0
? void 0
: <div style={{ marginLeft: '3px' }}>{n.children.map(c => <StateTreeNode plugin={this.props.plugin} nodeRef={c!} key={c} />)}</div>
: <div style={{ marginLeft: '7px', paddingLeft: '3px', borderLeft: '1px solid #999' }}>{n.children.map(c => <StateTreeNode plugin={this.props.plugin} state={this.props.state} nodeRef={c!} key={c} />)}</div>
}
</div>;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment