123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
- import { StateObject, State, Transform, StateObjectCell, Transformer } from 'mol-state';
- import * as React from 'react';
- import { PurePluginComponent } from '../base';
- import { ParameterControls, ParamOnChange } from '../controls/parameters';
- import { StateAction } from 'mol-state/action';
- import { PluginContext } from 'mol-plugin/context';
- import { ParamDefinition as PD } from 'mol-util/param-definition';
- import { Subject } from 'rxjs';
- export { StateTransformParameters, TransformContolBase };
- class StateTransformParameters extends PurePluginComponent<StateTransformParameters.Props> {
- validate(params: any) {
- // TODO
- return void 0;
- }
- areInitial(params: any) {
- return PD.areEqual(this.props.info.params, params, this.props.info.initialValues);
- }
- onChange: ParamOnChange = ({ name, value }) => {
- const params = { ...this.props.params, [name]: value };
- this.props.events.onChange(params, this.areInitial(params), this.validate(params));
- };
- render() {
- return <ParameterControls params={this.props.info.params} values={this.props.params} onChange={this.onChange} onEnter={this.props.events.onEnter} isDisabled={this.props.isDisabled} />;
- }
- }
- namespace StateTransformParameters {
- export interface Props {
- info: {
- params: PD.Params,
- initialValues: any,
- source: StateObject,
- isEmpty: boolean
- },
- events: {
- onChange: (params: any, areInitial: boolean, errors?: string[]) => void,
- onEnter: () => void,
- }
- params: any,
- isDisabled?: boolean
- }
- export type Class = React.ComponentClass<Props>
- export function infoFromAction(plugin: PluginContext, state: State, action: StateAction, nodeRef: Transform.Ref): Props['info'] {
- const source = state.cells.get(nodeRef)!.obj!;
- const params = action.definition.params ? action.definition.params(source, plugin) : { };
- const initialValues = PD.getDefaultValues(params);
- return {
- source,
- initialValues,
- params,
- isEmpty: Object.keys(params).length === 0
- };
- }
- export function infoFromTransform(plugin: PluginContext, state: State, transform: Transform): Props['info'] {
- const cell = state.cells.get(transform.ref)!;
- const source: StateObjectCell | undefined = (cell.sourceRef && state.cells.get(cell.sourceRef)!) || void 0;
- const create = transform.transformer.definition.params;
- const params = create ? create((source && source.obj) as any, plugin) : { };
- return {
- source: (source && source.obj) as any,
- initialValues: transform.params,
- params,
- isEmpty: Object.keys(params).length === 0
- }
- }
- }
- namespace TransformContolBase {
- export interface State {
- params: any,
- error?: string,
- busy: boolean,
- isInitial: boolean,
- isCollapsed?: boolean
- }
- }
- abstract class TransformContolBase<P, S extends TransformContolBase.State> extends PurePluginComponent<P, S> {
- abstract applyAction(): Promise<void>;
- abstract getInfo(): StateTransformParameters.Props['info'];
- abstract getHeader(): Transformer.Definition['display'];
- abstract getHeaderFallback(): string;
- abstract canApply(): boolean;
- abstract applyText(): string;
- abstract state: S;
- private busy: Subject<boolean>;
- private onEnter = () => {
- if (this.state.error) return;
- this.apply();
- }
- events: StateTransformParameters.Props['events'] = {
- onEnter: this.onEnter,
- onChange: (params, isInitial, errors) => this.setState({ params, isInitial, error: errors && errors[0] })
- }
- apply = async () => {
- this.setState({ busy: true });
- try {
- await this.applyAction();
- } finally {
- this.busy.next(false);
- }
- }
- init() {
- this.busy = new Subject();
- this.subscribe(this.busy, busy => this.setState({ busy }));
- }
- refresh = () => {
- this.setState({ params: this.getInfo().initialValues, isInitial: true, error: void 0 });
- }
- setDefault = () => {
- const info = this.getInfo();
- const params = PD.getDefaultValues(info.params);
- this.setState({ params, isInitial: PD.areEqual(info.params, params, info.initialValues), error: void 0 });
- }
- toggleExpanded = () => {
- this.setState({ isCollapsed: !this.state.isCollapsed });
- }
- render() {
- const info = this.getInfo();
- if (info.isEmpty) return null;
- const display = this.getHeader();
- return <div className='msp-transform-wrapper'>
- <div className='msp-transform-header'>
- <button className='msp-btn msp-btn-block' onClick={this.toggleExpanded}>{(display && display.name) || this.getHeaderFallback()}</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>}
- </div>
- {!this.state.isCollapsed && <>
- <StateTransformParameters info={info} events={this.events} params={this.state.params} isDisabled={this.state.busy} />
- <div className='msp-transform-apply-wrap'>
- <button className='msp-btn msp-btn-block msp-transform-refresh msp-form-control' title='Refresh params' onClick={this.refresh} disabled={this.state.busy || this.state.isInitial}>
- ↶ Reset
- </button>
- <div className='msp-transform-apply'>
- <button className={`msp-btn msp-btn-block msp-btn-commit msp-btn-commit-${this.canApply() ? 'on' : 'off'}`} onClick={this.apply} disabled={!this.canApply()}>
- {this.applyText()}
- </button>
- </div>
- </div>
- </>}
- </div>
- }
- }
|