diff --git a/src/mol-plugin-ui/controls/common.tsx b/src/mol-plugin-ui/controls/common.tsx index 0739a952da5babb37e5bb7f86ccb7d8d647d0323..de207ed8ae61c2cdea6d522155ac4739e909527d 100644 --- a/src/mol-plugin-ui/controls/common.tsx +++ b/src/mol-plugin-ui/controls/common.tsx @@ -8,6 +8,7 @@ import * as React from 'react'; import { Color } from '../../mol-util/color'; import { PurePluginUIComponent } from '../base'; import { IconName, Icon } from './icons'; +import { ShapeName, Shape } from './shapes'; export class ControlGroup extends React.Component<{ header: string, @@ -311,6 +312,7 @@ export type ToggleButtonProps = { label?: string | JSX.Element, title?: string, icon?: IconName, + shape?: ShapeName, isSelected?: boolean, toggle: () => void } @@ -327,6 +329,7 @@ export class ToggleButton extends React.PureComponent<ToggleButtonProps> { return <button onClick={this.onClick} title={this.props.title} disabled={props.disabled} style={props.style} className={props.className}> <Icon name={this.props.icon} /> + <Shape name={this.props.shape} /> {label && this.props.isSelected ? <b>{label}</b> : label} </button>; } diff --git a/src/mol-plugin-ui/controls/icons.tsx b/src/mol-plugin-ui/controls/icons.tsx index 4ee957fd03dc1d64a56d70e0f38c644d9c6732f1..9fc61594bba2cd3bf60dcbf7f77eb70c8b8a0e1a 100644 --- a/src/mol-plugin-ui/controls/icons.tsx +++ b/src/mol-plugin-ui/controls/icons.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; -export type IconName = +export type IconName = | '' | 'expand-layout' | 'plus' | 'minus' | 'reset-scene' | 'ok' | 'back' | 'block' | 'off' | 'expand' | 'collapse' | 'visual-visibility' | 'abort' | 'focus-on-visual' | 'settings' | 'tools' | 'log' | 'remove' | 'help' | 'help-circle' | 'info' | 'left-open-big' | 'right-open-big' | 'left-open' | 'right-open' | 'screenshot' | 'model-prev' | 'model-next' | 'model-first' | 'down-thin' | 'up-thin' | 'left-thin' | 'right-thin' diff --git a/src/mol-plugin-ui/controls/shapes.tsx b/src/mol-plugin-ui/controls/shapes.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0bd5c38b6215ff9dc31796abef875697f1968a61 --- /dev/null +++ b/src/mol-plugin-ui/controls/shapes.tsx @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import * as React from 'react'; + +export type ShapeName = + | '' | 'set' | 'intersect' | 'union' | 'subtract' + +export function Shape(props: { + name?: ShapeName, + style?: React.CSSProperties, + title?: string +}) { + const shape = getShape(props.name) + if (!shape) return null + return <span style={props.style} title={props.title}> + {shape} + </span>; +} + +function getShape(name?: ShapeName) { + switch (name) { + case 'union': return <Union /> + case 'subtract': return <Subtract /> + case 'intersect': return <Intersect /> + case 'set': return <Set /> + default: return null + } +} + +const circleLeft = <circle r="6px" id="circle-left" cy="16px" cx="12px" strokeWidth="1"/> +const circleRight = <circle r="6px" id="circle-right" cy="16px" cx="20px" strokeWidth="1"/> + +function Union() { + return <svg width="32px" height="32px"> + <defs> + {circleLeft} + {circleRight} + </defs> + <g> + <use href="#circle-left" className="msp-shape-filled"/> + <use href="#circle-right" className="msp-shape-filled"/> + </g> + </svg>; +} + +function Subtract() { + return <svg width="32px" height="32px"> + <defs> + {circleLeft} + {circleRight} + <mask id="mask-left"> + <use href="#circle-left" fill="white" stroke="white"/> + <use href="#circle-right" fill="black" strokeWidth="0" stroke="white"/> + </mask> + </defs> + <g> + <use href="#circle-left" className="msp-shape-filled" mask="url(#mask-left)"/> + <use href="#circle-right" className="msp-shape-empty"/> + </g> + </svg>; +} + +function Intersect() { + return <svg width="32px" height="32px"> + <defs> + {circleLeft} + {circleRight} + <clipPath id="clip-left"> + <use href="#circle-right"/> + </clipPath> + </defs> + <g> + <use href="#circle-left" className="msp-shape-filled" clipPath="url(#clip-left)"/> + <use href="#circle-left" className="msp-shape-empty"/> + <use href="#circle-right" className="msp-shape-empty"/> + </g> + </svg>; +} + +function Set() { + return <svg width="32px" height="32px"> + <defs> + {circleLeft} + {circleRight} + </defs> + <g> + <use href="#circle-left" className="msp-shape-filled"/> + <use href="#circle-right" className="msp-shape-empty"/> + </g> + </svg>; +} \ No newline at end of file diff --git a/src/mol-plugin-ui/skin/base/components/misc.scss b/src/mol-plugin-ui/skin/base/components/misc.scss index a37bb0d4367c29a9d3a6fe8a3ed2fc31b6ff0709..44a97bdfd1c144dc91acc2ba3251538de854f80f 100644 --- a/src/mol-plugin-ui/skin/base/components/misc.scss +++ b/src/mol-plugin-ui/skin/base/components/misc.scss @@ -78,13 +78,13 @@ margin: 0; text-align: center; padding-right: $control-spacing; - padding-left: $control-spacing; - + padding-left: $control-spacing; + &:hover { border-color: color-increase-contrast($msp-form-control-background, 5%) !important; border: none; outline-offset: -1px !important; - outline: 1px solid color-increase-contrast($msp-form-control-background, 20%) !important; + outline: 1px solid color-increase-contrast($msp-form-control-background, 20%) !important; } } @@ -97,7 +97,7 @@ .msp-btn { &:hover { outline-offset: -1px !important; - outline: 1px solid color-increase-contrast($msp-form-control-background, 20%) !important; + outline: 1px solid color-increase-contrast($msp-form-control-background, 20%) !important; } } } @@ -129,11 +129,11 @@ margin-bottom: 5px; padding: 0 10px; font-weight: 500; - background: $default-background; + background: $default-background; color: $font-color; } -.msp-left-panel-controls-buttons { +.msp-left-panel-controls-buttons { position: absolute; width: $row-height; top: 0; @@ -183,4 +183,14 @@ width: 32px; top: 0; } +} + +.msp-shape-filled { + fill: $font-color; + stroke: $font-color; +} + +.msp-shape-empty { + fill: none; + stroke: $font-color; } \ No newline at end of file diff --git a/src/mol-plugin-ui/structure/selection.tsx b/src/mol-plugin-ui/structure/selection.tsx index 45620ac84010fe6d79ac0ae1165b1f570bad230c..6c303ad758dc33d59dab2b4907d63d2038d4b404 100644 --- a/src/mol-plugin-ui/structure/selection.tsx +++ b/src/mol-plugin-ui/structure/selection.tsx @@ -134,14 +134,13 @@ export class StructureSelectionControls<P, S extends StructureSelectionControlsS toggleSet = this.showAction('set') toggleColor = this.showAction('color') - // TODO better icons get controls() { return <div> <div className='msp-control-row msp-select-row'> - <ToggleButton icon='plus' title='Add' toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} /> - <ToggleButton icon='minus' title='Remove' toggle={this.toggleRemove} isSelected={this.state.action === 'remove'} disabled={this.isDisabled} /> - <ToggleButton icon='star' title='Intersect' toggle={this.toggleIntersect} isSelected={this.state.action === 'intersect'} disabled={this.isDisabled} /> - <ToggleButton icon='flash' title='Set' toggle={this.toggleSet} isSelected={this.state.action === 'set'} disabled={this.isDisabled} /> + <ToggleButton shape='union' title='Add/Union' toggle={this.toggleAdd} isSelected={this.state.action === 'add'} disabled={this.isDisabled} /> + <ToggleButton shape='subtract' title='Remove/Subtract' toggle={this.toggleRemove} isSelected={this.state.action === 'remove'} disabled={this.isDisabled} /> + <ToggleButton shape='intersect' title='Intersect' toggle={this.toggleIntersect} isSelected={this.state.action === 'intersect'} disabled={this.isDisabled} /> + <ToggleButton shape='set' title='Set' toggle={this.toggleSet} isSelected={this.state.action === 'set'} disabled={this.isDisabled} /> <ToggleButton icon='brush' title='Color' toggle={this.toggleColor} isSelected={this.state.action === 'color'} disabled={this.isDisabled} /> </div> {(this.state.action && this.state.action !== 'color') && <ActionMenu items={this.queries} onSelect={this.selectQuery} />}