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

mol-plugin-ui: ActionMenu fixes

parent 70b94deb
No related branches found
No related tags found
No related merge requests found
......@@ -48,14 +48,16 @@ export namespace ActionMenu {
items: ActionMenu.Spec,
header?: string,
label?: string,
current?: ActionMenu.Item,
current?: Item,
onSelect: (value: any) => void
}
export class Toggle extends React.PureComponent<ToggleProps, { isSelected: boolean }> {
type ToggleState = { current?: Item, isSelected: boolean }
export class Toggle extends React.PureComponent<ToggleProps, ToggleState> {
private sub: Subscription | undefined = void 0;
state = { isSelected: false };
state = { isSelected: false, current: this.props.current };
componentDidMount() {
this.sub = this.props.menu.commands.subscribe(command => {
......@@ -85,6 +87,11 @@ export namespace ActionMenu {
this.props.menu.toggle(this.props);
}
static getDerivedStateFromProps(props: ToggleProps, state: ToggleState) {
if (props.current === state.current) return null;
return { isSelected: false, current: props.current };
}
render() {
const props = this.props;
const label = props.label || props.header;
......@@ -95,7 +102,9 @@ export namespace ActionMenu {
}
}
export class Options extends React.PureComponent<{ menu: ActionMenu }, { command: Command, isVisible: boolean }> {
type OptionsProps = { menu: ActionMenu, header?: string, items?: Spec, current?: Item | undefined }
export class Options extends React.PureComponent<OptionsProps, { command: Command, isVisible: boolean }> {
private sub: Subscription | undefined = void 0;
state = { isVisible: false, command: HideCmd };
......@@ -127,15 +136,21 @@ export namespace ActionMenu {
}
render() {
if (!this.state.isVisible || this.state.command.type !== 'toggle') return null;
const cmd = this.state.command;
if (!this.state.isVisible || cmd.type !== 'toggle') return null;
if (this.props.items) {
if (cmd.items !== this.props.items || cmd.current !== this.props.current) return null;
}
return <div className='msp-action-menu-options' style={{ marginTop: '1px' }}>
{this.state.command.header && <div className='msp-control-group-header' style={{ position: 'relative' }}>
{cmd.header && <div className='msp-control-group-header' style={{ position: 'relative' }}>
<button className='msp-btn msp-btn-block' onClick={this.hide}>
<Icon name='off' style={{ position: 'absolute', right: '2px', top: 0 }} />
<b>{this.state.command.header}</b>
<b>{cmd.header}</b>
</button>
</div>}
<Section menu={this.props.menu} items={this.state.command.items} onSelect={this.onSelect} current={this.state.command.current} />
<Section menu={this.props.menu} items={cmd.items} onSelect={this.onSelect} current={cmd.current} />
</div>
}
}
......
......@@ -71,7 +71,6 @@ export class ParameterMappingControl<S, T> extends PluginUIComponent<{ mapping:
}
}
function controlFor(param: PD.Any): ParamControl | undefined {
switch (param.type) {
case 'value': return void 0;
......@@ -128,6 +127,43 @@ export interface ParamProps<P extends PD.Base<any> = PD.Base<any>> {
}
export type ParamControl = React.ComponentClass<ParamProps<any>>
function renderSimple(options: { props: ParamProps<any>, state: { isExpanded: boolean }, control: JSX.Element, addOn: JSX.Element | null, toggleHelp: () => void }) {
const { props, state, control, toggleHelp, addOn } = options;
const _className = ['msp-control-row'];
if (props.param.shortLabel) _className.push('msp-control-label-short')
if (props.param.twoColumns) _className.push('msp-control-col-2')
const className = _className.join(' ');
const label = props.param.label || camelCaseToWords(props.name);
const help = props.param.help
? props.param.help(props.value)
: { description: props.param.description, legend: props.param.legend }
const desc = props.param.description;
const hasHelp = help.description || help.legend
return <>
<div className={className}>
<span title={desc}>
{label}
{hasHelp &&
<button className='msp-help msp-btn-link msp-btn-icon msp-control-group-expander' onClick={toggleHelp}
title={desc || `${state.isExpanded ? 'Hide' : 'Show'} help`}
style={{ background: 'transparent', textAlign: 'left', padding: '0' }}>
<span className={`msp-icon msp-icon-help-circle-${state.isExpanded ? 'collapse' : 'expand'}`} />
</button>
}
</span>
<div>
{control}
</div>
</div>
{hasHelp && state.isExpanded && <div className='msp-control-offset'>
<ParamHelp legend={help.legend} description={help.description} />
</div>}
{addOn}
</>;
}
export abstract class SimpleParam<P extends PD.Any> extends React.PureComponent<ParamProps<P>, { isExpanded: boolean }> {
state = { isExpanded: false };
......@@ -138,44 +174,16 @@ export abstract class SimpleParam<P extends PD.Any> extends React.PureComponent<
abstract renderControl(): JSX.Element;
renderAddOn(): JSX.Element | null { return null; }
private get className() {
const className = ['msp-control-row'];
if (this.props.param.shortLabel) className.push('msp-control-label-short')
if (this.props.param.twoColumns) className.push('msp-control-col-2')
return className.join(' ')
}
toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded });
toggleHelp = () => this.setState({ isExpanded: !this.state.isExpanded });
render() {
const label = this.props.param.label || camelCaseToWords(this.props.name);
const help = this.props.param.help
? this.props.param.help(this.props.value)
: { description: this.props.param.description, legend: this.props.param.legend }
const desc = this.props.param.description;
const hasHelp = help.description || help.legend
return <>
<div className={this.className}>
<span title={desc}>
{label}
{hasHelp &&
<button className='msp-help msp-btn-link msp-btn-icon msp-control-group-expander' onClick={this.toggleExpanded}
title={desc || `${this.state.isExpanded ? 'Hide' : 'Show'} help`}
style={{ background: 'transparent', textAlign: 'left', padding: '0' }}>
<span className={`msp-icon msp-icon-help-circle-${this.state.isExpanded ? 'collapse' : 'expand'}`} />
</button>
}
</span>
<div>
{this.renderControl()}
</div>
</div>
{hasHelp && this.state.isExpanded && <div className='msp-control-offset'>
<ParamHelp legend={help.legend} description={help.description} />
</div>}
{this.renderAddOn()}
</>;
return renderSimple({
props: this.props,
state: this.state,
control: this.renderControl(),
toggleHelp: this.toggleHelp,
addOn: this.renderAddOn()
});
}
}
......@@ -340,7 +348,10 @@ export class SelectControl extends SimpleParam<PD.Select<string | number>> {
}
renderAddOn() {
return <ActionMenu.Options menu={this.menu} />;
const items = this.items(this.props.param);
const current = ActionMenu.findCurrent(items, this.props.value);
return <ActionMenu.Options menu={this.menu} items={items} current={current} />;
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment