Select & delete edges

This commit is contained in:
futpib 2018-11-11 16:08:51 +03:00
parent 1c5f7e017e
commit a507e1a6c3
6 changed files with 92 additions and 34 deletions

View File

@ -16,6 +16,10 @@ module.exports = createActionCreators({
MOVE_SOURCE_OUTPUT: (sourceOutputIndex, destSourceIndex) => ({ sourceOutputIndex, destSourceIndex }),
KILL_CLIENT_BY_INDEX: clientIndex => ({ clientIndex }),
KILL_SINK_INPUT_BY_INDEX: sinkInputIndex => ({ sinkInputIndex }),
KILL_SOURCE_OUTPUT_BY_INDEX: sourceOutputIndex => ({ sourceOutputIndex }),
UNLOAD_MODULE_BY_INDEX: moduleIndex => ({ moduleIndex }),
},
});

View File

@ -101,7 +101,7 @@ class Edge extends EdgeBase {
});
return r.g({
className: 'edge-container',
className: 'edge-container ' + (this.props.className || ''),
'data-source': data.source,
'data-target': data.target,
}, [

View File

@ -148,6 +148,19 @@ const Module = Client;
const gridDotSize = 2;
const gridSpacing = 36;
const Marker = ({ id, d }) => r('marker', {
id,
viewBox: '0 -8 16 16',
refX: '16',
markerWidth: '16',
markerHeight: '16',
orient: 'auto',
}, r.path({
className: 'arrow',
d,
}));
const renderDefs = () => r(React.Fragment, [
r.pattern({
id: 'background-pattern',
@ -162,29 +175,26 @@ const renderDefs = () => r(React.Fragment, [
r: gridDotSize,
})),
r('marker', {
r(Marker, {
id: 'my-source-arrow',
viewBox: '0 -8 16 16',
refX: '16',
markerWidth: '16',
markerHeight: '16',
orient: 'auto',
}, r.path({
className: 'arrow',
d: 'M 16,-8 L 0,0 L 16,8',
})),
}),
r('marker', {
r(Marker, {
id: 'my-sink-arrow',
viewBox: '0 -8 16 16',
refX: '16',
markerWidth: '16',
markerHeight: '16',
orient: 'auto',
}, r.path({
className: 'arrow',
d: 'M 0,-8 L 16,0 L 0,8',
})),
}),
// WORKAROUND: `context-fill` did not work
r(Marker, {
id: 'my-source-arrow-selected',
d: 'M 16,-8 L 0,0 L 16,8',
}),
r(Marker, {
id: 'my-sink-arrow-selected',
d: 'M 0,-8 L 16,0 L 0,8',
}),
]);
const renderNode = (nodeRef, data, key, selected, hovered) => r({
@ -262,13 +272,12 @@ const renderNodeText = state => dgo => r('foreignObject', {
state,
})));
const afterRenderEdge = (id, element, edge, edgeContainer) => {
if (edge.type) {
edgeContainer.classList.add(edge.type);
}
};
const renderEdge = edgeProps => r(Edge, edgeProps);
const renderEdge = props => r(Edge, {
classSet: {
[props.data.type]: true,
},
...props,
});
const renderEdgeText = state => ({ data, transform }) => r('foreignObject', {
transform,
@ -361,7 +370,8 @@ class Graph extends React.Component {
}
}
onSelectEdge() {
onSelectEdge(selected) {
this.setState({ selected });
}
onCreateEdge() {
@ -375,7 +385,12 @@ class Graph extends React.Component {
}
}
onDeleteEdge() {
onDeleteEdge(selected) {
if (selected.type === 'sinkInput') {
this.props.killSinkInputByIndex(selected.index);
} else if (selected.type === 'sourceOutput') {
this.props.killSourceOutputByIndex(selected.index);
}
}
render() {
@ -488,7 +503,7 @@ class Graph extends React.Component {
showGraphControls: false,
edgeArrowSize: 128,
edgeArrowSize: 64,
backgroundFillId: '#background-pattern',
@ -499,8 +514,6 @@ class Graph extends React.Component {
renderEdge,
renderEdgeText: renderEdgeText(this.props),
afterRenderEdge,
}));
}
}

View File

@ -43,6 +43,8 @@ class GraphView extends React.Component {
onSwapEdge: this.onSwapEdge.bind(this),
onNodeMove: this.onNodeMove.bind(this),
onSelectEdge: this.onSelectEdge.bind(this),
renderNode: this.renderNode.bind(this),
renderNodeText: this.renderNodeText.bind(this),
@ -96,6 +98,11 @@ class GraphView extends React.Component {
}
}
onSelectEdge(edge) {
const originalEdge = satelliteEdgeToOriginalEdge.get(edge);
this.props.onSelectEdge(originalEdge);
}
renderNode(nodeRef, dgo, key, selected, hovered) {
if (dgo.type !== 'satellite') {
return this.props.renderNode(nodeRef, dgo, key, selected, hovered);
@ -127,6 +134,8 @@ class GraphView extends React.Component {
return satelliteNodes.concat(node);
}, this.props.nodes));
let { selected } = this.props;
const edges = flatten(values(mapObjIndexed((edges, target) => mapIndexed((edge, i) => {
const satelliteEdge = {
id: edge.id,
@ -136,6 +145,11 @@ class GraphView extends React.Component {
index: edge.index,
type: edge.type,
};
if (edge === selected) {
selected = satelliteEdge;
}
satelliteEdgeToOriginalEdge.set(satelliteEdge, edge);
return satelliteEdge;
}, edges), edgesByTargetNodeKey)));
@ -143,6 +157,8 @@ class GraphView extends React.Component {
return r(GraphViewBase, {
...this.props,
selected,
ref: this.graph,
nodes,
@ -151,10 +167,12 @@ class GraphView extends React.Component {
onSwapEdge: this.onSwapEdge,
onNodeMove: this.onNodeMove,
onSelectEdge: this.onSelectEdge,
renderNode: this.renderNode,
renderNodeText: this.renderNodeText,
afterRenderEdge: this.afterRenderEdge,
afterRenderEdge: this.props.afterRenderEdge && this.afterRenderEdge,
});
}
}

View File

@ -63,15 +63,27 @@ button:active {
color: var(--themeSelectedFgColor);
}
.view-wrapper .graph .edge.selected {
stroke: var(--themeSelectedBgColor);
}
#my-source-arrow-selected > .arrow, #my-sink-arrow-selected > .arrow {
fill: var(--themeSelectedBgColor);
}
.view-wrapper .sourceOutput .edge {
/* marker-end: none; */
/* marker-start: url(#start-arrow); */
marker-end: url(#my-source-arrow);
}
.view-wrapper .sourceOutput .edge.selected {
marker-end: url(#my-source-arrow-selected);
}
.view-wrapper .sinkInput .edge {
marker-end: url(#my-sink-arrow);
}
.view-wrapper .sinkInput .edge.selected {
marker-end: url(#my-sink-arrow-selected);
}
#edge-custom-container .edge {
marker-end: none;

View File

@ -109,10 +109,21 @@ module.exports = store => {
pa.moveSourceOutput(sourceOutputIndex, destSourceIndex, rethrow);
return state;
},
[pulseActions.killClientByIndex]: (state, { payload: { clientIndex } }) => {
pa.killClientByIndex(clientIndex, rethrow);
return state;
},
[pulseActions.killSinkInputByIndex]: (state, { payload: { sinkInputIndex } }) => {
pa.killSinkInputByIndex(sinkInputIndex, rethrow);
return state;
},
[pulseActions.killSourceOutputByIndex]: (state, { payload: { sourceOutputIndex } }) => {
pa.killSourceOutputByIndex(sourceOutputIndex, rethrow);
return state;
},
[pulseActions.unloadModuleByIndex]: (state, { payload: { moduleIndex } }) => {
pa.unloadModuleByIndex(moduleIndex, rethrow);
return state;