184 lines
5.5 KiB
JavaScript
184 lines
5.5 KiB
JavaScript
import React, { Component } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
|
|
import CanGraph from './CanGraph';
|
|
|
|
require('element-closest');
|
|
|
|
export default class CanGraphList extends Component {
|
|
static propTypes = {
|
|
plottedSignals: PropTypes.array.isRequired,
|
|
messages: PropTypes.object.isRequired,
|
|
onGraphTimeClick: PropTypes.func.isRequired,
|
|
seekTime: PropTypes.number.isRequired,
|
|
onSegmentChanged: PropTypes.func.isRequired,
|
|
onSignalUnplotPressed: PropTypes.func.isRequired,
|
|
segment: PropTypes.array.isRequired,
|
|
mergePlots: PropTypes.func.isRequired
|
|
};
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
draggingSignal: {},
|
|
dragPos: null,
|
|
dragShift: null,
|
|
graphToReceiveDrop: null
|
|
};
|
|
|
|
this.plotListRef = null;
|
|
this.plotRefs = [];
|
|
this.renderSignalPlot = this.renderSignalPlot.bind(this);
|
|
this.onPlotListRefReady = this.onPlotListRefReady.bind(this);
|
|
this.onGraphDragStart = this.onGraphDragStart.bind(this);
|
|
this.onGraphDragEnd = this.onGraphDragEnd.bind(this);
|
|
this.onMouseMove = this.onMouseMove.bind(this);
|
|
}
|
|
|
|
onGraphDragStart(messageId, signalUid, shiftX, shiftY) {
|
|
this.setState({
|
|
draggingSignal: { messageId, signalUid },
|
|
dragShift: { x: shiftX, y: shiftY }
|
|
});
|
|
}
|
|
|
|
determineDraggingGraph() {
|
|
const { draggingSignal } = this.state;
|
|
return this.plotRefs.find(
|
|
({ messageId, signalUid }) => draggingSignal.messageId === messageId
|
|
&& draggingSignal.signalUid === signalUid
|
|
);
|
|
}
|
|
|
|
onMouseMove(e) {
|
|
const { dragShift } = this.state;
|
|
if (dragShift === null) {
|
|
if (this.state.graphToReceiveDrop !== null) {
|
|
this.setState({ graphToReceiveDrop: null });
|
|
}
|
|
return;
|
|
}
|
|
const rect = this.plotListRef.getBoundingClientRect();
|
|
const draggingGraph = this.determineDraggingGraph();
|
|
if (draggingGraph) {
|
|
draggingGraph.ref.hidden = true;
|
|
const ele = document.elementFromPoint(e.clientX, e.clientY);
|
|
draggingGraph.ref.hidden = false;
|
|
const closestPlot = ele.closest('.cabana-explorer-visuals-plot');
|
|
const closestPlotRef = this.plotRefs.find(
|
|
({ ref, messageId, signalUid }) => !(
|
|
messageId === draggingGraph.messageId
|
|
&& signalUid === draggingGraph.signalUid
|
|
) && ref.isEqualNode(closestPlot)
|
|
);
|
|
if (closestPlotRef) {
|
|
this.setState({ graphToReceiveDrop: closestPlotRef });
|
|
} else {
|
|
this.setState({ graphToReceiveDrop: null });
|
|
}
|
|
}
|
|
const left = e.clientX - rect.left - dragShift.x;
|
|
const top = e.clientY - rect.top - dragShift.y;
|
|
|
|
this.setState({ dragPos: { left, top } });
|
|
}
|
|
|
|
onGraphDragEnd() {
|
|
if (this.state.graphToReceiveDrop !== null) {
|
|
this.props.mergePlots({
|
|
fromPlot: this.state.draggingSignal,
|
|
toPlot: this.state.graphToReceiveDrop
|
|
});
|
|
}
|
|
|
|
this.setState({
|
|
draggingSignal: {},
|
|
dragShift: null,
|
|
dragPos: null,
|
|
graphToReceiveDrop: null
|
|
});
|
|
}
|
|
|
|
addCanGraphRef(ref, messageId, signalUid) {
|
|
if (ref) {
|
|
let { plotRefs } = this;
|
|
plotRefs = plotRefs
|
|
.filter(
|
|
(ref) => !(ref.messageId === messageId && ref.signalUid === signalUid)
|
|
)
|
|
.concat([{ messageId, signalUid, ref }]);
|
|
this.plotRefs = plotRefs;
|
|
}
|
|
}
|
|
|
|
renderSignalPlot(plottedSignals, index) {
|
|
const { draggingSignal, graphToReceiveDrop } = this.state;
|
|
const { messageId, signalUid } = plottedSignals[0];
|
|
const msg = this.props.messages[messageId];
|
|
const signal = Object.values(msg.frame.signals).find(
|
|
(s) => s.uid === signalUid
|
|
);
|
|
|
|
if (!this.plotListRef) {
|
|
return [];
|
|
}
|
|
|
|
const isDragging = draggingSignal.signalUid === signalUid
|
|
&& draggingSignal.messageId === messageId;
|
|
const canReceiveGraphDrop = graphToReceiveDrop
|
|
&& graphToReceiveDrop.signalUid === signalUid
|
|
&& graphToReceiveDrop.messageId === messageId;
|
|
plottedSignals = plottedSignals.map((plottedSignal) => ({
|
|
messageName: this.props.messages[plottedSignal.messageId].frame.name,
|
|
...plottedSignal
|
|
}));
|
|
const key = plottedSignals.reduce(
|
|
(key, { messageId, signalUid }) => `${key + messageId}_${signalUid}`,
|
|
''
|
|
);
|
|
return (
|
|
<CanGraph
|
|
onGraphRefAvailable={(ref) => {
|
|
this.addCanGraphRef(ref, messageId, signalUid);
|
|
}}
|
|
key={key}
|
|
unplot={this.props.onSignalUnplotPressed}
|
|
messages={this.props.messages}
|
|
messageId={messageId}
|
|
messageName={msg.frame ? msg.frame.name : null}
|
|
signalSpec={Object.assign(Object.create(signal), signal)}
|
|
onSegmentChanged={this.props.onSegmentChanged}
|
|
segment={this.props.segment}
|
|
onRelativeTimeClick={this.props.onGraphTimeClick}
|
|
currentTime={this.props.seekTime}
|
|
onDragStart={this.onGraphDragStart}
|
|
onDragEnd={this.onGraphDragEnd}
|
|
container={this.plotListRef}
|
|
dragPos={isDragging ? this.state.dragPos : null}
|
|
canReceiveGraphDrop={canReceiveGraphDrop}
|
|
plottedSignals={plottedSignals}
|
|
live={this.props.live}
|
|
/>
|
|
);
|
|
}
|
|
|
|
onPlotListRefReady(ref) {
|
|
this.plotListRef = ref;
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<div
|
|
className="cabana-explorer-visuals-plots"
|
|
ref={this.onPlotListRefReady}
|
|
onMouseMove={this.onMouseMove}
|
|
onMouseLeave={this.onGraphDragEnd}
|
|
onMouseUp={this.onGraphDragEnd}
|
|
>
|
|
{this.props.plottedSignals.map(this.renderSignalPlot)}
|
|
</div>
|
|
);
|
|
}
|
|
}
|