Skip to content
Snippets Groups Projects
Select Git revision
  • 0dc0c74d90dea38a8eff1692e8854d2169dcce36
  • master default protected
  • rednatco-v2
  • rednatco
  • test
  • ntc-tube-uniform-color
  • ntc-tube-missing-atoms
  • restore-vertex-array-per-program
  • watlas2
  • dnatco_new
  • cleanup-old-nodejs
  • webmmb
  • fix_auth_seq_id
  • update_deps
  • ext_dev
  • ntc_balls
  • nci-2
  • plugin
  • bugfix-0.4.5
  • nci
  • servers
  • v0.5.0-dev.1
  • v0.4.5
  • v0.4.4
  • v0.4.3
  • v0.4.2
  • v0.4.1
  • v0.4.0
  • v0.3.12
  • v0.3.11
  • v0.3.10
  • v0.3.9
  • v0.3.8
  • v0.3.7
  • v0.3.6
  • v0.3.5
  • v0.3.4
  • v0.3.3
  • v0.3.2
  • v0.3.1
  • v0.3.0
41 results

int-tuple.ts

Blame
  • generic.tsx 5.66 KiB
    /**
     * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
     *
     * @author Alexander Rose <alexander.rose@weirdbyte.de>
     * @author David Sehnal <david.sehnal@gmail.com>
     */
    
    import * as React from 'react';
    import { StructureHierarchyRef } from '../../mol-plugin-state/manager/structure/hierarchy-state';
    import { PluginCommands } from '../../mol-plugin/commands';
    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() {
            return this.plugin.managers.structure.hierarchy.behaviors.selection;
        }
    
        componentDidMount() {
            this.subscribe(this.current, () => this.forceUpdate());
        }
    
        get unitcell() {
            const { selection } = this.plugin.managers.structure.hierarchy;
            if (selection.structures.length === 0) return null;
    
            const refs = [];
            for (const s of selection.structures) {
                const model = s.model;
                if (model?.unitcell && model.unitcell?.cell.obj) refs.push(model.unitcell);
            }
            if (refs.length === 0) return null;
    
            return <GenericEntry refs={refs} labelMultiple='Unit Cells' />;
        }
    
        get customControls(): JSX.Element[] | null {
            const controls: JSX.Element[] = [];
            this.plugin.genericRepresentationControls.forEach((provider, key) => {
                const [refs, labelMultiple] = provider(this.plugin.managers.structure.hierarchy.selection);
                if (refs.length > 0) {
                    controls.push(<div key={key}>
                        <GenericEntry refs={refs} labelMultiple={labelMultiple} />
                    </div>);
                }
            });
            return controls.length > 0 ? controls : null;
        }
    
        render() {
            return <>
                <div style={{ marginTop: '6px' }}>
                    {this.unitcell}
                    {this.customControls}
                </div>
            </>;
        }
    }
    
    export class GenericEntry<T extends StructureHierarchyRef> extends PurePluginUIComponent<{ refs: T[], labelMultiple?: string }, { showOptions: boolean }> {
        state = { showOptions: false };
    
        componentDidMount() {
            this.subscribe(this.plugin.state.events.cell.stateUpdated, e => {
                if (State.ObjectEvent.isCell(e, this.pivot?.cell)) this.forceUpdate();
            });
        }
    
        get pivot() { return this.props.refs[0]; }
    
        toggleVisibility = (e: React.MouseEvent<HTMLElement>) => {
            e.preventDefault();
            this.plugin.managers.structure.hierarchy.toggleVisibility(this.props.refs);
            e.currentTarget.blur();
        };
    
        highlight = (e: React.MouseEvent<HTMLElement>) => {
            e.preventDefault();
            if (!this.pivot.cell.parent) return;
            PluginCommands.Interactivity.Object.Highlight(this.plugin, {
                state: this.pivot.cell.parent,
                ref: this.props.refs.map(c => c.cell.transform.ref)
            });
        };
    
        clearHighlight = (e: React.MouseEvent<HTMLElement>) => {
            e.preventDefault();
            PluginCommands.Interactivity.ClearHighlights(this.plugin);
        };
    
        focus = (e: React.MouseEvent<HTMLElement>) => {
            e.preventDefault();
    
            let allHidden = true;
            for (const uc of this.props.refs) {
                if (!uc.cell.state.isHidden) {
                    allHidden = false;
                    break;
                }
            }
    
            if (allHidden) {
                this.plugin.managers.structure.hierarchy.toggleVisibility(this.props.refs, 'show');
            }
    
            const loci = [];
            for (const uc of this.props.refs) {
                if (uc.cell.state.isHidden) {
                    continue;
                }
    
                const l = uc.cell.obj?.data.repr.getLoci();
                if (l) loci.push(l);
            }
            this.plugin.managers.camera.focusLoci(loci);
        };
    
        toggleOptions = () => this.setState({ showOptions: !this.state.showOptions });
    
        render() {
            const { refs, labelMultiple } = this.props;
            if (refs.length === 0) return null;
    
            const pivot = refs[0];
    
            let label, description;
            if (refs.length === 1) {
                const { obj } = pivot.cell;
                if (!obj) return null;
                label = obj?.label;
                description = obj?.description;
            } else {
                label = `${refs.length} ${labelMultiple || 'Objects'}`;
            }
    
            return <>
                <div className='msp-flex-row'>
                    <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 ? 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'>
                        <UpdateTransformControl state={pivot.cell.parent} transform={pivot.cell.transform} customHeader='none' autoHideApply />
                    </div>
                </>}
            </>;
        }
    }