2017-05-29 17:52:17 -06:00
|
|
|
import React, {Component} from 'react';
|
|
|
|
import Vega from 'react-vega';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
|
|
|
import Signal from '../models/can/signal';
|
|
|
|
import CanPlot from '../vega/CanPlot';
|
|
|
|
|
|
|
|
export default class CanGraph extends Component {
|
2017-06-13 18:40:05 -06:00
|
|
|
static MAX_POINTS = 10000;
|
|
|
|
|
2017-05-29 17:52:17 -06:00
|
|
|
static propTypes = {
|
|
|
|
data: PropTypes.array,
|
2017-06-30 23:09:13 -06:00
|
|
|
messageId: PropTypes.string,
|
2017-05-29 17:52:17 -06:00
|
|
|
messageName: PropTypes.string,
|
|
|
|
signalSpec: PropTypes.instanceOf(Signal),
|
2017-06-13 18:40:05 -06:00
|
|
|
segment: PropTypes.array,
|
|
|
|
unplot: PropTypes.func,
|
2017-06-13 22:17:40 -06:00
|
|
|
onRelativeTimeClick: PropTypes.func,
|
2017-06-16 16:45:19 -06:00
|
|
|
currentTime: PropTypes.number,
|
|
|
|
onSegmentChanged: PropTypes.func
|
2017-05-29 17:52:17 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.onNewView = this.onNewView.bind(this);
|
2017-06-13 18:40:05 -06:00
|
|
|
this.onSignalClickTime = this.onSignalClickTime.bind(this);
|
2017-06-16 16:45:19 -06:00
|
|
|
this.onSignalSegment = this.onSignalSegment.bind(this);
|
2017-05-29 17:52:17 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
segmentIsNew(newSegment) {
|
|
|
|
return newSegment.length != this.props.segment.length
|
|
|
|
|| !(newSegment.every((val, idx) => this.props.segment[idx] == val));
|
|
|
|
}
|
|
|
|
|
2017-06-26 13:22:06 -06:00
|
|
|
dataChanged(prevProps, nextProps) {
|
|
|
|
return nextProps.data.length != prevProps.data.length
|
2017-06-30 20:46:34 -06:00
|
|
|
|| !(prevProps.signalSpec.equals(nextProps.signalSpec))
|
|
|
|
|| prevProps.data.some((prevEntry, idx) => prevEntry.y != nextProps.data[idx].y);
|
2017-06-26 13:22:06 -06:00
|
|
|
}
|
|
|
|
|
2017-05-29 17:52:17 -06:00
|
|
|
shouldComponentUpdate(nextProps, nextState) {
|
|
|
|
if(this.view) {
|
|
|
|
// only update if segment is new
|
2017-06-13 18:40:05 -06:00
|
|
|
let segmentChanged = false;
|
2017-06-16 22:41:15 -06:00
|
|
|
if(this.segmentIsNew(nextProps.segment)) {
|
|
|
|
if(nextProps.segment.length > 0) {
|
|
|
|
// Set segmented domain
|
|
|
|
this.view.signal('segment', nextProps.segment)
|
|
|
|
} else {
|
|
|
|
// Reset segment to full domain
|
2017-06-16 23:33:19 -06:00
|
|
|
this.view.signal('segment', 0);
|
2017-06-16 22:41:15 -06:00
|
|
|
}
|
|
|
|
segmentChanged = true;
|
|
|
|
}
|
2017-06-13 18:40:05 -06:00
|
|
|
|
|
|
|
if(nextProps.currentTime != this.props.currentTime) {
|
|
|
|
this.view.signal('videoTime', nextProps.currentTime);
|
|
|
|
segmentChanged = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(segmentChanged) {
|
2017-05-29 17:52:17 -06:00
|
|
|
this.view.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-26 13:22:06 -06:00
|
|
|
return this.dataChanged(this.props, nextProps);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidUpdate(prevProps, prevState) {
|
|
|
|
if(this.dataChanged(prevProps, this.props)) {
|
|
|
|
this.view.run();
|
|
|
|
}
|
|
|
|
|
2017-05-29 17:52:17 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
onNewView(view) {
|
|
|
|
this.view = view;
|
|
|
|
if(this.props.segment.length > 0) {
|
|
|
|
view.signal('segment', this.props.segment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-13 18:40:05 -06:00
|
|
|
onSignalClickTime(signal, clickTime) {
|
|
|
|
if(clickTime !== undefined) {
|
2017-06-30 23:09:13 -06:00
|
|
|
this.props.onRelativeTimeClick(this.props.messageId, clickTime);
|
2017-06-13 18:40:05 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-16 16:45:19 -06:00
|
|
|
onSignalSegment(signal, segment) {
|
2017-06-16 22:41:15 -06:00
|
|
|
if(!Array.isArray(segment)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-06-30 23:09:13 -06:00
|
|
|
this.props.onSegmentChanged(this.props.messageId, segment);
|
2017-06-16 22:41:15 -06:00
|
|
|
if(this.view) {
|
|
|
|
const state = this.view.getState();
|
|
|
|
state.subcontext[0].signals.brush = 0;
|
|
|
|
this.view = this.view.setState(state);
|
|
|
|
}
|
2017-06-16 16:45:19 -06:00
|
|
|
}
|
|
|
|
|
2017-05-29 17:52:17 -06:00
|
|
|
render() {
|
2017-07-17 19:10:37 -06:00
|
|
|
return (
|
|
|
|
<div className='cabana-explorer-visuals-plot'>
|
|
|
|
<div className='cabana-explorer-visuals-plot-message'>
|
|
|
|
<span>{this.props.messageName}</span>
|
|
|
|
</div>
|
|
|
|
<div className='cabana-explorer-visuals-plot-signal'>
|
|
|
|
<strong>{this.props.signalSpec.name}</strong>
|
|
|
|
<a onClick={this.props.unplot}>(unplot)</a>
|
|
|
|
</div>
|
|
|
|
<CanPlot
|
|
|
|
className='cabana-explorer-visuals-plot-canvas'
|
|
|
|
logLevel={0}
|
|
|
|
data={{table: this.props.data}}
|
|
|
|
onNewView={this.onNewView}
|
|
|
|
onSignalClickTime={this.onSignalClickTime}
|
|
|
|
onSignalSegment={this.onSignalSegment}/>
|
|
|
|
</div>
|
|
|
|
);
|
2017-05-29 17:52:17 -06:00
|
|
|
}
|
|
|
|
}
|