diff --git a/packages/xod-client/src/core/styles/components/Link.scss b/packages/xod-client/src/core/styles/components/Link.scss index 354cccb4..bef4b317 100644 --- a/packages/xod-client/src/core/styles/components/Link.scss +++ b/packages/xod-client/src/core/styles/components/Link.scss @@ -1,33 +1,40 @@ +@mixin link-parts-coloring($type-color) { + .line { + stroke: $type-color; + } + + .end { + fill: $type-color; + } +} .Link { - stroke: grey; - stroke-width: 2px; + .line { + stroke: grey; + stroke-width: 2px; + } &.string { - stroke: $color-datatype-string; + @include link-parts-coloring($color-datatype-string); } &.number { - stroke: $color-datatype-number; + @include link-parts-coloring($color-datatype-number); } &.bool { - stroke: $color-datatype-bool; + @include link-parts-coloring($color-datatype-bool); } &.pulse { - stroke: $color-datatype-pulse; + @include link-parts-coloring($color-datatype-pulse); } &:hover { - .line { - stroke: white; - } + @include link-parts-coloring(white); } &.is-selected { - .line { - stroke: #4ed5ec; - } + @include link-parts-coloring($color-canvas-selected); } } diff --git a/packages/xod-client/src/core/styles/components/Pin.scss b/packages/xod-client/src/core/styles/components/Pin.scss index c1e23423..32f180d2 100644 --- a/packages/xod-client/src/core/styles/components/Pin.scss +++ b/packages/xod-client/src/core/styles/components/Pin.scss @@ -1,17 +1,8 @@ @mixin symbol-coloring($type-color) { stroke: $type-color; - $hover-color: lighten($type-color, 25%); - - &:hover { - stroke: $hover-color - } - &.is-connected { fill: $type-color; - &:hover { - fill: $hover-color - } } } @@ -22,10 +13,6 @@ stroke-width: 2px; filter: url(#dropshadow); - &:hover { - fill: color-canvas-hover($color-pin-fill); - } - &.string { @include symbol-coloring($color-datatype-string); } @@ -43,20 +30,24 @@ } } - .label { - font-family: $font-family-condensed; - font-weight: 500; - font-size: 12px; - dominant-baseline: central; - } + &:hover { + .symbol { + &.string { + @include symbol-coloring(lighten($color-datatype-string, 25%)); + } - .label.input { - fill: $color-pinlabel-input; - } + &.number { + @include symbol-coloring(lighten($color-datatype-number, 25%)); + } - .label.output { - fill: $color-pinlabel-output; - font-weight: 700; // black font looks thinner + &.bool { + @include symbol-coloring(lighten($color-datatype-bool, 25%)); + } + + &.pulse { + @include symbol-coloring(lighten($color-datatype-pulse, 25%)); + } + } } .linkingHighlight { @@ -77,6 +68,4 @@ fill: $color-canvas-selected; } } - - } diff --git a/packages/xod-client/src/core/styles/components/PinLabel.scss b/packages/xod-client/src/core/styles/components/PinLabel.scss new file mode 100644 index 00000000..f6c5d861 --- /dev/null +++ b/packages/xod-client/src/core/styles/components/PinLabel.scss @@ -0,0 +1,15 @@ +.PinLabel { + font-family: $font-family-condensed; + font-weight: 500; + font-size: 12px; + dominant-baseline: central; +} + +.PinLabel.input { + fill: $color-pinlabel-input; +} + +.PinLabel.output { + fill: $color-pinlabel-output; + font-weight: 700; // black font looks thinner +} \ No newline at end of file diff --git a/packages/xod-client/src/core/styles/main.scss b/packages/xod-client/src/core/styles/main.scss index 06e3586e..cf6a5eac 100644 --- a/packages/xod-client/src/core/styles/main.scss +++ b/packages/xod-client/src/core/styles/main.scss @@ -26,6 +26,7 @@ 'components/Node', 'components/NodeText', 'components/Pin', + 'components/PinLabel', 'components/Link', 'components/PopupAlert', 'components/PopupPrompt', diff --git a/packages/xod-client/src/editor/containers/Patch.jsx b/packages/xod-client/src/editor/containers/Patch.jsx index aa287dfd..a3599ea8 100644 --- a/packages/xod-client/src/editor/containers/Patch.jsx +++ b/packages/xod-client/src/editor/containers/Patch.jsx @@ -18,6 +18,7 @@ import NodesLayer from '../../project/components/NodesLayer'; import LinksLayer from '../../project/components/LinksLayer'; import GhostsLayer from '../../project/components/GhostsLayer'; import SnappingPreviewLayer from '../../project/components/SnappingPreviewLayer'; +import DraggedNodeLayer from '../../project/components/DraggedNodeLayer'; import { addNodesPositioning, addLinksPositioning, @@ -47,6 +48,9 @@ class Patch extends React.Component { this.onLinkClick = this.onLinkClick.bind(this); this.deselectAll = this.deselectAll.bind(this); + + this.getDraggedNodeId = this.getDraggedNodeId.bind(this); + this.extendNodesByPinValidness = this.extendNodesByPinValidness.bind(this); } shouldComponentUpdate(nextProps, nextState) { @@ -171,8 +175,11 @@ class Patch extends React.Component { } getNodes() { - const nodes = R.values(this.props.nodes); - return this.extendNodesByPinValidness(nodes); + return R.compose( + this.extendNodesByPinValidness, + R.values, + R.omit([this.getDraggedNodeId()]) // we are rendering dragged node in a separate layer + )(this.props.nodes); } getLinks() { return R.values(this.props.links); @@ -259,6 +266,7 @@ class Patch extends React.Component { } render() { + const draggedNodeId = this.getDraggedNodeId(); const nodes = this.getNodes(); const links = this.getLinks(); @@ -276,19 +284,23 @@ class Patch extends React.Component { height={this.props.size.height} onClick={this.deselectAll} /> + - + + + ); + } +} + +DraggedNodeLayer.propTypes = { + draggedNodeId: React.PropTypes.any, + nodes: React.PropTypes.any, +}; + +export default DraggedNodeLayer; diff --git a/packages/xod-client/src/project/components/Link.jsx b/packages/xod-client/src/project/components/Link.jsx index 676fad99..8d441394 100644 --- a/packages/xod-client/src/project/components/Link.jsx +++ b/packages/xod-client/src/project/components/Link.jsx @@ -3,6 +3,7 @@ import classNames from 'classnames'; import { SIZE } from 'xod-core'; import { noop } from '../../utils/ramda'; +import { PIN_RADIUS } from '../nodeLayout'; class Link extends React.Component { constructor(props) { @@ -48,6 +49,8 @@ class Link extends React.Component { const clickable = this.isClickable(); const pointerEvents = (clickable) ? 'all' : 'none'; + const linkEndRadius = PIN_RADIUS - 3; + return ( + + ); } diff --git a/packages/xod-client/src/project/components/Node.jsx b/packages/xod-client/src/project/components/Node.jsx index 2d240011..03a54998 100644 --- a/packages/xod-client/src/project/components/Node.jsx +++ b/packages/xod-client/src/project/components/Node.jsx @@ -3,6 +3,7 @@ import React from 'react'; import classNames from 'classnames'; import Pin from './Pin'; +import PinLabel from './PinLabel'; import NodeText from './NodeText'; import { noop } from '../../utils/ramda'; @@ -12,13 +13,8 @@ class Node extends React.Component { constructor(props) { super(props); this.id = this.props.id; - - // needed for distinguishing between mouseDown events on pins and on node body - this.pinListRef = null; - - this.assignPinListRef = this.assignPinListRef.bind(this); - this.onMouseDown = this.onMouseDown.bind(this); + this.onPinMouseUp = this.onPinMouseUp.bind(this); this.onPinMouseDown = this.onPinMouseDown.bind(this); } @@ -28,11 +24,6 @@ class Node extends React.Component { } onMouseDown(event) { - if (this.pinListRef && this.pinListRef.contains(event.target)) { - event.preventDefault(); - return; - } - this.props.onMouseDown(event, this.id); } @@ -44,10 +35,6 @@ class Node extends React.Component { this.props.onPinMouseDown(this.id, pinId); } - assignPinListRef(ref) { - this.pinListRef = ref; - } - render() { const { size, @@ -76,16 +63,12 @@ class Node extends React.Component { return ( - + - + + {pinsArr.map(pin => - + + + + )} diff --git a/packages/xod-client/src/project/components/Pin.jsx b/packages/xod-client/src/project/components/Pin.jsx index d05d2197..240eb67b 100644 --- a/packages/xod-client/src/project/components/Pin.jsx +++ b/packages/xod-client/src/project/components/Pin.jsx @@ -1,10 +1,8 @@ import React from 'react'; import classNames from 'classnames'; -import { PIN_DIRECTION, PIN_VALIDITY } from 'xod-core'; +import { PIN_VALIDITY } from 'xod-core'; import { noop } from '../../utils/ramda'; - -const PIN_RADIUS = 6; -const TEXT_OFFSET_FROM_PIN_BORDER = 10; +import { PIN_RADIUS } from '../nodeLayout'; export default class Pin extends React.Component { constructor(props) { @@ -57,39 +55,11 @@ export default class Pin extends React.Component { }; } - getTextProps() { - const textVerticalOffset = PIN_RADIUS + TEXT_OFFSET_FROM_PIN_BORDER; - const pos = this.getPinCenter(); - return { - x: pos.x, - y: pos.y + (textVerticalOffset * (this.isInput() ? 1 : -1)), - textAnchor: 'middle', - }; - } - - getDirection() { - return this.props.direction; - } - - isInput() { - return (this.getDirection() === PIN_DIRECTION.INPUT); - } - isInjected() { return !!this.props.injected; } render() { - const pinLabel = this.props.pinLabel ? ( - - {this.props.pinLabel} - - ) : null; - const cls = classNames('Pin', { 'is-property': this.isInjected(), 'is-selected': this.props.isSelected, @@ -125,7 +95,6 @@ export default class Pin extends React.Component { r="15" /> {symbol} - {pinLabel} ); } @@ -134,9 +103,7 @@ export default class Pin extends React.Component { Pin.propTypes = { keyName: React.PropTypes.string.isRequired, injected: React.PropTypes.bool, - pinLabel: React.PropTypes.string, type: React.PropTypes.string, - direction: React.PropTypes.string.isRequired, position: React.PropTypes.object.isRequired, onMouseUp: React.PropTypes.func.isRequired, onMouseDown: React.PropTypes.func.isRequired, diff --git a/packages/xod-client/src/project/components/PinLabel.jsx b/packages/xod-client/src/project/components/PinLabel.jsx new file mode 100644 index 00000000..9d649fda --- /dev/null +++ b/packages/xod-client/src/project/components/PinLabel.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { PIN_DIRECTION } from 'xod-core'; + +import { PIN_RADIUS, TEXT_OFFSET_FROM_PIN_BORDER } from '../nodeLayout'; + +export default class Pin extends React.Component { + getPinCenter() { + return this.props.position; + } + + getTextProps() { + const textVerticalOffset = PIN_RADIUS + TEXT_OFFSET_FROM_PIN_BORDER; + const pos = this.getPinCenter(); + return { + x: pos.x, + y: pos.y + (textVerticalOffset * (this.isInput() ? 1 : -1)), + textAnchor: 'middle', + }; + } + + getDirection() { + return this.props.direction; + } + + isInput() { + return (this.getDirection() === PIN_DIRECTION.INPUT); + } + + render() { + return this.props.pinLabel ? ( + + {this.props.pinLabel} + + ) : null; + } +} + +Pin.propTypes = { + keyName: React.PropTypes.string.isRequired, + pinLabel: React.PropTypes.string, + direction: React.PropTypes.string.isRequired, + position: React.PropTypes.object.isRequired, +}; diff --git a/packages/xod-client/src/project/nodeLayout.js b/packages/xod-client/src/project/nodeLayout.js index 2c4ebbcd..489fe368 100644 --- a/packages/xod-client/src/project/nodeLayout.js +++ b/packages/xod-client/src/project/nodeLayout.js @@ -20,6 +20,8 @@ export const PIN_MARGIN = { }; export const NODE_CORNER_RADIUS = 5; +export const PIN_RADIUS = 6; +export const TEXT_OFFSET_FROM_PIN_BORDER = 10; /** * @param {number} pinCount diff --git a/packages/xod-client/stories/Link.jsx b/packages/xod-client/stories/Link.jsx new file mode 100644 index 00000000..cdaaf549 --- /dev/null +++ b/packages/xod-client/stories/Link.jsx @@ -0,0 +1,68 @@ +import React from 'react'; +import { storiesOf } from '@kadira/storybook'; + +import '../src/core/styles/main.scss'; +import XODLink from '../src/project/components/Link'; + +const pFrom = { x: 30, y: 30 }; +const pTo = { x: 120, y: 120 }; + +const baseProps = { + id: 'qwerty', + from: pFrom, + to: pTo, + isGhost: false, + isSelected: false, + type: 'string', +}; + +storiesOf('Link', module) + .addDecorator(story => ( + + + + + {story()} + + )) + .add('string', () => ( + + )) + .add('bool', () => ( + + )) + .add('number', () => ( + + )) + .add('pulse', () => ( + + )) + .add('selected', () => ( + + )); + diff --git a/packages/xod-client/stories/Pin.jsx b/packages/xod-client/stories/Pin.jsx index 71969ac7..92788272 100644 --- a/packages/xod-client/stories/Pin.jsx +++ b/packages/xod-client/stories/Pin.jsx @@ -34,16 +34,9 @@ storiesOf('Pin', module) {story()} )) - .add('input', () => ( + .add('default', () => ( - )) - .add('output', () => ( - )) .add('selected', () => ( diff --git a/packages/xod-client/stories/PinLabel.jsx b/packages/xod-client/stories/PinLabel.jsx new file mode 100644 index 00000000..492549a7 --- /dev/null +++ b/packages/xod-client/stories/PinLabel.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { storiesOf } from '@kadira/storybook'; + +import '../src/core/styles/main.scss'; +import PinLabel from '../src/project/components/PinLabel'; + +const pinCenter = { x: 70, y: 70 }; + +const baseProps = { + keyName: "my pin's keyname", + pinLabel: 'PIN', + direction: 'input', + position: pinCenter, +}; + +storiesOf('PinLabel', module) + .addDecorator(story => ( + + + + + + cross line indicates center + position passed to pin + + {story()} + + )) + .add('input', () => ( + + )) + .add('output', () => ( + + )); +