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

mol-plugin: wip UI

parent 86ec6e87
No related branches found
No related tags found
No related merge requests found
...@@ -4,23 +4,21 @@ ...@@ -4,23 +4,21 @@
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
*/ */
import { List } from 'immutable';
import { PluginState } from 'mol-plugin/state';
import { formatTime } from 'mol-util';
import { LogEntry } from 'mol-util/log-entry';
import * as React from 'react'; import * as React from 'react';
import { PluginContext } from '../context'; import { PluginContext } from '../context';
import { StateTree } from './state/tree'; import { PluginReactContext, PluginUIComponent } from './base';
import { Viewport, ViewportControls } from './viewport';
import { Controls, TrajectoryControls, LociLabelControl } from './controls';
import { PluginUIComponent, PluginReactContext } from './base';
import { CameraSnapshots } from './camera'; import { CameraSnapshots } from './camera';
import { Controls, LociLabelControl, TrajectoryControls } from './controls';
import { StateSnapshots } from './state'; import { StateSnapshots } from './state';
import { List } from 'immutable'; import { StateObjectActions } from './state/actions';
import { LogEntry } from 'mol-util/log-entry';
import { formatTime } from 'mol-util';
import { BackgroundTaskProgress } from './task';
import { ApplyActionContol } from './state/apply-action';
import { PluginState } from 'mol-plugin/state';
import { UpdateTransformContol } from './state/update-transform';
import { StateObjectCell } from 'mol-state';
import { AnimationControls } from './state/animation'; import { AnimationControls } from './state/animation';
import { StateTree } from './state/tree';
import { BackgroundTaskProgress } from './task';
import { Viewport, ViewportControls } from './viewport';
export class Plugin extends React.Component<{ plugin: PluginContext }, {}> { export class Plugin extends React.Component<{ plugin: PluginContext }, {}> {
...@@ -105,8 +103,8 @@ export class State extends PluginUIComponent { ...@@ -105,8 +103,8 @@ export class State extends PluginUIComponent {
const kind = this.plugin.state.behavior.kind.value; const kind = this.plugin.state.behavior.kind.value;
return <div className='msp-scrollable-container'> return <div className='msp-scrollable-container'>
<div className='msp-btn-row-group msp-data-beh'> <div className='msp-btn-row-group msp-data-beh'>
<button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.set('data')} style={{ fontWeight: kind === 'data' ? 'bold' : 'normal'}}>Data</button> <button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.set('data')} style={{ fontWeight: kind === 'data' ? 'bold' : 'normal' }}>Data</button>
<button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.set('behavior')} style={{ fontWeight: kind === 'behavior' ? 'bold' : 'normal'}}>Behavior</button> <button className='msp-btn msp-btn-block msp-form-control' onClick={() => this.set('behavior')} style={{ fontWeight: kind === 'behavior' ? 'bold' : 'normal' }}>Behavior</button>
</div> </div>
<StateTree state={kind === 'data' ? this.plugin.state.dataState : this.plugin.state.behaviorState} /> <StateTree state={kind === 'data' ? this.plugin.state.dataState : this.plugin.state.behaviorState} />
</div> </div>
...@@ -172,21 +170,13 @@ export class CurrentObject extends PluginUIComponent { ...@@ -172,21 +170,13 @@ export class CurrentObject extends PluginUIComponent {
const current = this.current; const current = this.current;
const ref = current.ref; const ref = current.ref;
const cell = current.state.cells.get(ref)!; const cell = current.state.cells.get(ref)!;
const parent: StateObjectCell | undefined = (cell.sourceRef && current.state.cells.get(cell.sourceRef)!) || void 0;
const transform = cell.transform; const transform = cell.transform;
const def = transform.transformer.definition; const def = transform.transformer.definition;
const display = cell.obj ? cell.obj.label : (def.display && def.display.name) || def.name;
const actions = current.state.actions.fromCell(cell, this.plugin); return cell.status === 'ok' && <>
return <> <div className='msp-section-header'>{`Actions (${display})`}</div>
<div className='msp-current-header'> <StateObjectActions state={current.state} nodeRef={ref} />
{cell.obj ? cell.obj.label : (def.display && def.display.name) || def.name}
</div>
{(parent && parent.status === 'ok') && <UpdateTransformContol state={current.state} transform={transform} />}
{cell.status === 'ok' && <>
<div className='msp-section-header'>Actions</div>
{actions.map((act, i) => <ApplyActionContol plugin={this.plugin} key={`${act.id}`} state={current.state} action={act} nodeRef={ref} />)}
</>}
</>; </>;
} }
} }
\ No newline at end of file
/**
* Copyright (c) 2018 - 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import * as React from 'react';
import { PluginUIComponent } from '../base';
import { ApplyActionContol } from './apply-action';
import { State } from 'mol-state';
export class StateObjectActions extends PluginUIComponent<{ state: State, nodeRef: string }> {
get current() {
return this.plugin.state.behavior.currentObject.value;
}
componentDidMount() {
this.subscribe(this.plugin.state.behavior.currentObject, o => {
this.forceUpdate();
});
this.subscribe(this.plugin.events.state.object.updated, ({ ref, state }) => {
const current = this.current;
if (current.ref !== ref || current.state !== state) return;
this.forceUpdate();
});
}
render() {
const { state, nodeRef: ref } = this.props;
const cell = state.cells.get(ref)!;
const actions = state.actions.fromCell(cell, this.plugin);
return actions.map((act, i) => <ApplyActionContol plugin={this.plugin} key={`${act.id}`} state={state} action={act} nodeRef={ref} />);
}
}
\ No newline at end of file
...@@ -166,7 +166,7 @@ abstract class TransformContolBase<P, S extends TransformContolBase.ControlState ...@@ -166,7 +166,7 @@ abstract class TransformContolBase<P, S extends TransformContolBase.ControlState
render() { render() {
const info = this.getInfo(); const info = this.getInfo();
if (info.isEmpty && this.isUpdate()) return null; const isEmpty = info.isEmpty && this.isUpdate();
const display = this.getHeader(); const display = this.getHeader();
...@@ -178,9 +178,9 @@ abstract class TransformContolBase<P, S extends TransformContolBase.ControlState ...@@ -178,9 +178,9 @@ abstract class TransformContolBase<P, S extends TransformContolBase.ControlState
return <div className='msp-transform-wrapper'> return <div className='msp-transform-wrapper'>
<div className='msp-transform-header'> <div className='msp-transform-header'>
<button className='msp-btn msp-btn-block' onClick={this.toggleExpanded}>{display.name}</button> <button className='msp-btn msp-btn-block' onClick={this.toggleExpanded}>{display.name}</button>
{!this.state.isCollapsed && <button className='msp-btn msp-btn-link msp-transform-default-params' onClick={this.setDefault} disabled={this.state.busy} style={{ float: 'right'}} title='Set default params'></button>} {!isEmpty && !this.state.isCollapsed && <button className='msp-btn msp-btn-link msp-transform-default-params' onClick={this.setDefault} disabled={this.state.busy} style={{ float: 'right'}} title='Set default params'></button>}
</div> </div>
{!this.state.isCollapsed && <> {!isEmpty && !this.state.isCollapsed && <>
<ParamEditor info={info} events={this.events} params={this.state.params} isDisabled={this.state.busy} /> <ParamEditor info={info} events={this.events} params={this.state.params} isDisabled={this.state.busy} />
<div className='msp-transform-apply-wrap'> <div className='msp-transform-apply-wrap'>
......
/** /**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * Copyright (c) 2018 - 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
* *
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
*/ */
import * as React from 'react'; import * as React from 'react';
import { PluginStateObject } from 'mol-plugin/state/objects'; import { PluginStateObject } from 'mol-plugin/state/objects';
import { State, StateObject } from 'mol-state' import { State, StateObject, StateObjectCell, StateTransform } from 'mol-state'
import { PluginCommands } from 'mol-plugin/command'; import { PluginCommands } from 'mol-plugin/command';
import { PluginUIComponent } from '../base'; import { PluginUIComponent } from '../base';
import { UpdateTransformContol } from './update-transform';
import { StateObjectActions } from './actions';
export class StateTree extends PluginUIComponent<{ state: State }, { showActions: boolean }> {
state = { showActions: true };
componentDidMount() {
this.subscribe(this.plugin.events.state.cell.created, e => {
if (e.cell.transform.parent === StateTransform.RootRef) this.forceUpdate();
});
this.subscribe(this.plugin.events.state.cell.removed, e => {
if (e.parent === StateTransform.RootRef) this.forceUpdate();
});
}
static getDerivedStateFromProps(props: { state: State }, state: { showActions: boolean }) {
const n = props.state.tree.root.ref;
const children = props.state.tree.children.get(n);
const showActions = children.size === 0;
if (state.showActions === showActions) return null;
return { showActions };
}
export class StateTree extends PluginUIComponent<{ state: State }> {
render() { render() {
const n = this.props.state.tree.root.ref; const ref = this.props.state.tree.root.ref;
return <StateTreeNode state={this.props.state} nodeRef={n} depth={0} />; if (this.state.showActions) {
return <StateObjectActions state={this.props.state} nodeRef={ref} />
}
return <StateTreeNode state={this.props.state} nodeRef={ref} depth={0} />;
} }
} }
...@@ -195,7 +220,7 @@ class StateTreeNodeLabel extends PluginUIComponent<{ nodeRef: string, state: Sta ...@@ -195,7 +220,7 @@ class StateTreeNodeLabel extends PluginUIComponent<{ nodeRef: string, state: Sta
<span className='msp-icon msp-icon-visual-visibility' /> <span className='msp-icon msp-icon-visual-visibility' />
</button>; </button>;
return <div className={`msp-tree-row${isCurrent ? ' msp-tree-row-current' : ''}`} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight} const row = <div className={`msp-tree-row${isCurrent ? ' msp-tree-row-current' : ''}`} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight}
style={{ marginLeft: this.state.isCurrent ? '0px' : `${this.props.depth * 10}px`, borderRadius: this.state.isCurrent ? '0' : void 0 }}> style={{ marginLeft: this.state.isCurrent ? '0px' : `${this.props.depth * 10}px`, borderRadius: this.state.isCurrent ? '0' : void 0 }}>
{isCurrent ? <b>{label}</b> : label} {isCurrent ? <b>{label}</b> : label}
{children.size > 0 && <button onClick={this.toggleExpanded} className='msp-btn msp-btn-link msp-tree-toggle-exp-button'> {children.size > 0 && <button onClick={this.toggleExpanded} className='msp-btn msp-btn-link msp-tree-toggle-exp-button'>
...@@ -205,5 +230,27 @@ class StateTreeNodeLabel extends PluginUIComponent<{ nodeRef: string, state: Sta ...@@ -205,5 +230,27 @@ class StateTreeNodeLabel extends PluginUIComponent<{ nodeRef: string, state: Sta
<span className='msp-icon msp-icon-remove' /> <span className='msp-icon msp-icon-remove' />
</button>}{visibility} </button>}{visibility}
</div>; </div>;
if (this.state.isCurrent) {
return <>
{row}
<StateTreeNodeTransform {...this.props}/>
</>
}
return row;
}
}
class StateTreeNodeTransform extends PluginUIComponent<{ nodeRef: string, state: State, depth: number }, { isExpanded: boolean }> {
render() {
const ref = this.props.nodeRef;
const cell = this.props.state.cells.get(ref)!;
const parent: StateObjectCell | undefined = (cell.sourceRef && this.props.state.cells.get(cell.sourceRef)!) || void 0;
if (!parent || parent.status !== 'ok') return null;
const transform = cell.transform;
return <UpdateTransformContol state={this.props.state} transform={transform} />;
} }
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment