diff --git a/src/components/AddSignals.js b/src/components/AddSignals.js
index 0ac41a0..dec9c44 100644
--- a/src/components/AddSignals.js
+++ b/src/components/AddSignals.js
@@ -68,16 +68,6 @@ export default class AddSignals extends Component {
dragSignal: null,
dragCurrentBit: null
};
-
- this.updateSignalStyles = this.updateSignalStyles.bind(this);
- this.onSignalHover = this.onSignalHover.bind(this);
- this.onBitHover = this.onBitHover.bind(this);
- this.onSignalHoverEnd = this.onSignalHoverEnd.bind(this);
- this.onTentativeSignalChange = this.onTentativeSignalChange.bind(this);
- this.onSignalChange = this.onSignalChange.bind(this);
- this.onSignalRemove = this.onSignalRemove.bind(this);
- this.onSignalPlotChange = this.onSignalPlotChange.bind(this);
- this.resetDragState = this.resetDragState.bind(this);
}
copySignals(signals) {
@@ -124,11 +114,11 @@ export default class AddSignals extends Component {
return style;
}
- updateSignalStyles() {
+ updateSignalStyles = () => {
const signalStyles = this.calcSignalStyles(this.state.signals);
this.setState({ signalStyles });
- }
+ };
calcSignalStyles(signals) {
const signalStyles = {};
@@ -160,11 +150,11 @@ export default class AddSignals extends Component {
})[0];
}
- onSignalHover(signal) {
+ onSignalHover = signal => {
if (!signal) return;
this.setState({ highlightedSignal: signal.name }, this.updateSignalStyles);
- }
+ };
signalBitIndex(bitIdx, signal) {
// todo does this work for both big and little endian?
@@ -175,7 +165,7 @@ export default class AddSignals extends Component {
return bitIdx - startBit;
}
- onBitHover(bitIdx, signal) {
+ onBitHover = (bitIdx, signal) => {
let { dragStartBit, signals, dragSignal } = this.state;
if (dragStartBit !== null) {
@@ -279,13 +269,13 @@ export default class AddSignals extends Component {
if (signal) {
this.onSignalHover(signal);
}
- }
+ };
- onSignalHoverEnd(signal) {
+ onSignalHoverEnd = signal => {
if (!signal) return;
this.setState({ highlightedSignal: null }, this.updateSignalStyles);
- }
+ };
nextNewSignalName() {
const existingNames = Object.keys(this.state.signals);
@@ -440,10 +430,11 @@ export default class AddSignals extends Component {
}
renderBitMatrix() {
+ const { message } = this.props;
const rows = [];
let rowCount;
- if (this.props.message.frame && this.props.message.frame.size) {
- rowCount = Math.floor(this.props.message.frame.size * 8 / 8);
+ if (message.frame && message.frame.size) {
+ rowCount = Math.floor(message.frame.size * 8 / 8);
} else {
rowCount = 8;
}
@@ -483,11 +474,7 @@ export default class AddSignals extends Component {
);
}
- rowBits.push(
-
- {this.byteValueHex(i)}
- |
- );
+ rowBits.push({this.byteValueHex(i)} | );
rows.push({rowBits}
);
}
@@ -500,23 +487,23 @@ export default class AddSignals extends Component {
);
}
- resetDragState() {
+ resetDragState = () => {
this.setState({
dragStartBit: null,
dragSignal: null,
dragCurrentBit: null
});
- }
+ };
- onTentativeSignalChange(signal) {
+ onTentativeSignalChange = signal => {
// Tentative signal changes are not propagated up
// but their effects are displayed in the bitmatrix
const { signals } = this.state;
signals[signal.name] = signal;
this.setState({ signals });
- }
+ };
- onSignalChange(signal, oldSignal) {
+ onSignalChange = (signal, oldSignal) => {
const { signals } = this.state;
for (let signalName in signals) {
@@ -527,13 +514,13 @@ export default class AddSignals extends Component {
signals[signal.name] = signal;
this.setState({ signals }, this.propagateUpSignalChange);
- }
+ };
- onSignalRemove(signal) {
+ onSignalRemove = signal => {
const { signals } = this.state;
delete signals[signal.name];
this.setState({ signals }, this.propagateUpSignalChange);
- }
+ };
propagateUpSignalChange() {
const { signals } = this.state;
@@ -544,11 +531,11 @@ export default class AddSignals extends Component {
);
}
- onSignalPlotChange(shouldPlot, signalUid) {
+ onSignalPlotChange = (shouldPlot, signalUid) => {
const { message } = this.props;
this.props.onSignalPlotChange(shouldPlot, message.id, signalUid);
- }
+ };
render() {
return (
diff --git a/src/components/SignalLegend.js b/src/components/SignalLegend.js
index 4228f3d..d2e7140 100644
--- a/src/components/SignalLegend.js
+++ b/src/components/SignalLegend.js
@@ -18,15 +18,11 @@ export default class SignalLegend extends Component {
plottedSignalUids: PropTypes.array
};
- constructor(props) {
- super(props);
- this.state = {
- expandedSignals: []
- };
- this.toggleExpandSignal = this.toggleExpandSignal.bind(this);
- }
+ state = {
+ expandedSignals: []
+ };
- toggleExpandSignal(s) {
+ toggleExpandSignal = s => {
const { expandedSignals } = this.state;
if (!expandedSignals.includes(s.uid)) {
const updatedExpandedSignals = [...expandedSignals, s.uid];
@@ -35,7 +31,7 @@ export default class SignalLegend extends Component {
const updatedExpandedSignals = expandedSignals.filter(i => i !== s.uid);
this.setState({ expandedSignals: updatedExpandedSignals });
}
- }
+ };
checkExpandedSignal(s) {
return this.state.expandedSignals.includes(s);
diff --git a/src/components/SignalLegend/signalLegend.scss b/src/components/SignalLegend/signalLegend.scss
index 81a410f..09beb54 100644
--- a/src/components/SignalLegend/signalLegend.scss
+++ b/src/components/SignalLegend/signalLegend.scss
@@ -42,19 +42,6 @@
display: block;
}
}
- &.is-highlighted {
- .signals-legend-entry-color {
- opacity: 0.5;
- }
- }
- &-color {
- display: block;
- height: 100%;
- left: 0;
- opacity: 0.3;
- position: absolute;
- width: 1.5%;
- }
&-header {
border-bottom: 1px solid transparent;
cursor: pointer;
diff --git a/src/components/SignalLegendEntry.js b/src/components/SignalLegendEntry.js
deleted file mode 100644
index f4889d1..0000000
--- a/src/components/SignalLegendEntry.js
+++ /dev/null
@@ -1,398 +0,0 @@
-// SignalLegendEntry.js
-
-import React, { Component } from "react";
-import PropTypes from "prop-types";
-import cx from "classnames";
-
-import Signal from "../models/can/signal";
-import DbcUtils from "../utils/dbc";
-import { swapKeysAndValues } from "../utils/object";
-
-export default class SignalLegendEntry extends Component {
- static propTypes = {
- signal: PropTypes.instanceOf(Signal).isRequired,
- isHighlighted: PropTypes.bool,
- onSignalHover: PropTypes.func,
- onSignalHoverEnd: PropTypes.func,
- onTentativeSignalChange: PropTypes.func,
- onSignalChange: PropTypes.func,
- onSignalRemove: PropTypes.func,
- onSignalPlotChange: PropTypes.func,
- toggleExpandSignal: PropTypes.func,
- isPlotted: PropTypes.bool,
- isExpanded: PropTypes.bool
- };
-
- static unsignedTransformation = field => {
- return (value, signal) => {
- if (value !== "") {
- value = Number(value) || 0;
-
- if (value < 0) {
- value = 0;
- }
- }
- signal[field] = value;
- return signal;
- };
- };
-
- static fields = [
- {
- field: "name",
- title: "Name",
- type: "string"
- },
- {
- field: "size",
- title: "Size",
- type: "number",
- transform: SignalLegendEntry.unsignedTransformation("size")
- },
- {
- field: "startBit",
- title: signal =>
- signal.isLittleEndian
- ? "Least significant bit"
- : "Most significant bit",
- type: "number",
- transform: SignalLegendEntry.unsignedTransformation("startBit")
- },
- {
- field: "isLittleEndian",
- title: "Endianness",
- type: "option",
- options: {
- options: ["Little", "Big"],
- optionValues: { Little: true, Big: false }
- },
- transform: (isLittleEndian, signal) => {
- if (signal.isLittleEndian !== isLittleEndian) {
- const { startBit } = signal;
-
- if (isLittleEndian) {
- // big endian -> little endian
- const startByte = Math.floor(signal.startBit / 8),
- endByte = Math.floor((signal.startBit - signal.size + 1) / 8);
-
- if (startByte === endByte) {
- signal.startBit = signal.startBit - signal.size + 1;
- } else {
- signal.startBit = DbcUtils.matrixBitNumber(startBit);
- }
- } else {
- // little endian -> big endian
- const startByte = Math.floor(signal.startBit / 8),
- endByte = Math.floor((signal.startBit + signal.size - 1) / 8);
-
- if (startByte === endByte) {
- signal.startBit = signal.startBit + signal.size - 1;
- } else {
- signal.startBit = DbcUtils.bigEndianBitIndex(startBit);
- }
- }
- signal.isLittleEndian = isLittleEndian;
- }
- return signal;
- }
- },
- {
- field: "isSigned",
- title: "Sign",
- type: "option",
- options: {
- options: ["Signed", "Unsigned"],
- optionValues: { Signed: true, Unsigned: false }
- }
- },
- {
- field: "factor",
- title: "Factor",
- type: "number"
- },
- {
- field: "offset",
- title: "Offset",
- type: "number"
- },
- {
- field: "unit",
- title: "Unit",
- type: "string"
- },
- {
- field: "comment",
- title: "Comment",
- type: "string"
- },
- {
- field: "min",
- title: "Minimum value",
- type: "number"
- },
- {
- field: "max",
- title: "Maximum value",
- type: "number"
- }
- ];
-
- static fieldSpecForName = name => {
- return SignalLegendEntry.fields.find(field => field.field === name);
- };
-
- constructor(props) {
- super(props);
- this.state = {
- isExpanded: false,
- signalEdited: Object.assign(Object.create(props.signal), props.signal)
- };
-
- this.toggleEditing = this.toggleEditing.bind(this);
- this.updateField = this.updateField.bind(this);
- this.toggleSignalPlot = this.toggleSignalPlot.bind(this);
- }
-
- componentWillReceiveProps(nextProps) {
- if (!nextProps.signal.equals(this.props.signal)) {
- this.setState({
- signalEdited: Object.assign(
- Object.create(nextProps.signal),
- nextProps.signal
- )
- });
- }
- }
-
- renderField(field, title, valueCol, signal) {
- let titleStr;
- if (typeof title === "function") {
- titleStr = title(signal);
- } else {
- titleStr = title;
- }
-
- return (
-
-
- {valueCol}
-
- );
- }
-
- updateField(fieldSpec, value) {
- let { signalEdited } = this.state;
- const { signal } = this.props;
-
- if (fieldSpec.transform) {
- signalEdited = fieldSpec.transform(value, signalEdited);
- } else {
- signalEdited[fieldSpec.field] = value;
- }
-
- // Save entire signal while editing
- this.setState({ signalEdited });
- const signalCopy = Object.assign(Object.create(signal), signal);
- Object.entries(signalEdited).forEach(([field, value]) => {
- signalCopy[field] = value;
- });
- this.props.onSignalChange(signalCopy, signal);
- }
-
- renderNumberField(fieldSpec, signal) {
- const { field, title } = fieldSpec;
- let valueCol;
-
- if (this.props.isExpanded) {
- let value = this.state.signalEdited[field];
- if (value !== "") {
- let num = Number(value);
- value = isNaN(num) ? "" : num;
- }
- valueCol = (
- {
- this.updateField(fieldSpec, e.target.value);
- }}
- />
- );
- } else {
- let value = this.props.signal[field];
- valueCol = {value};
- }
- return this.renderField(field, title, valueCol, signal);
- }
-
- renderStringField(fieldSpec, signal) {
- const { field, title } = fieldSpec;
- let valueCol;
- if (this.props.isExpanded) {
- valueCol = (
- {
- this.updateField(fieldSpec, e.target.value);
- }}
- />
- );
- } else {
- valueCol = {this.props.signal[field]};
- }
-
- return this.renderField(field, title, valueCol, signal);
- }
-
- renderOptionField(fieldSpec, signal) {
- let valueCol;
- const { field, title } = fieldSpec;
- const { options, optionValues } = fieldSpec.options;
- let valueOptions = swapKeysAndValues(optionValues);
-
- if (this.props.isExpanded) {
- const optionEles = options.map(opt => (
-
- ));
- valueCol = (
-
- );
- } else {
- valueCol = {valueOptions[this.props.signal[field]]};
- }
-
- return this.renderField(field, title, valueCol, signal);
- }
-
- renderFieldNode(field, signal) {
- if (field.type === "number") {
- return this.renderNumberField(field, signal);
- } else if (field.type === "option") {
- return this.renderOptionField(field, signal);
- } else if (field.type === "string") {
- return this.renderStringField(field, signal);
- }
- }
-
- toggleEditing(e) {
- let { signalEdited } = this.state;
- const { signal, isExpanded } = this.props;
- const signalCopy = Object.assign(Object.create(signal), signal);
-
- if (isExpanded) {
- // Finished editing, save changes & reset intermediate
- // signalEdited state.
- Object.entries(signalEdited).forEach(([field, value]) => {
- const fieldSpec = SignalLegendEntry.fieldSpecForName(field);
-
- if (
- fieldSpec &&
- fieldSpec.type === "number" &&
- isNaN(parseInt(value, 10))
- ) {
- value = 0;
- }
-
- signalCopy[field] = value;
- });
- this.props.onSignalChange(signalCopy, signal);
- } else {
- signalEdited = signalCopy;
- }
-
- // Expand and enable signal editing
- this.setState({
- signalEdited
- });
- this.props.toggleExpandSignal(signal);
- e.stopPropagation();
- }
-
- renderSignalForm(signal) {
- return (
-
- {SignalLegendEntry.fields.map(field => {
- return (
-
- {this.renderFieldNode(field, signal)}
-
- );
- })}
-
-
-
-
- );
- }
-
- toggleSignalPlot(e) {
- const { signal, isPlotted } = this.props;
- e.preventDefault();
- this.props.onSignalPlotChange(!isPlotted, signal.uid);
- }
-
- render() {
- const { signal } = this.props;
- const expandedEntryClass = this.props.isExpanded ? "is-expanded" : null;
- const highlightedEntryClass = this.props.isHighlighted
- ? "is-highlighted"
- : null;
- const plottedButtonClass = this.props.isPlotted
- ? "button"
- : "button--alpha";
- const plottedButtonText = this.props.isPlotted ? "Hide Plot" : "Show Plot";
- return (
- this.props.onSignalHover(signal)}
- onMouseLeave={() => this.props.onSignalHoverEnd(signal)}
- >
-
-
-
- {signal.name}
-
-
-
-
-
-
- {this.props.isExpanded ? this.renderSignalForm(signal) : null}
-
-
- );
- }
-}
diff --git a/src/components/SignalLegendEntry/ColorBar.js b/src/components/SignalLegendEntry/ColorBar.js
new file mode 100644
index 0000000..aae9daa
--- /dev/null
+++ b/src/components/SignalLegendEntry/ColorBar.js
@@ -0,0 +1,12 @@
+import styled from "react-emotion";
+
+// color bar on the left side of the signals legend
+export default styled("div")`
+ display: block;
+ height: 100%;
+ left: 0;
+ position: absolute;
+ width: 1.5%;
+ opacity: ${({ isHighlighted }) => (isHighlighted ? 0.5 : 0.3)};
+ background-color: rgb(${({ rgb }) => rgb.join(",")});
+`;
diff --git a/src/components/SignalLegendEntry/FIELDS.js b/src/components/SignalLegendEntry/FIELDS.js
new file mode 100644
index 0000000..457084e
--- /dev/null
+++ b/src/components/SignalLegendEntry/FIELDS.js
@@ -0,0 +1,113 @@
+import DbcUtils from "../../utils/dbc";
+
+const unsignedTransformation = field => {
+ return (value, signal) => {
+ if (value !== "") {
+ value = Number(value) || 0;
+
+ if (value < 0) {
+ value = 0;
+ }
+ }
+ signal[field] = value;
+ return signal;
+ };
+};
+
+export default [
+ {
+ field: "name",
+ title: "Name",
+ type: "string"
+ },
+ {
+ field: "size",
+ title: "Size",
+ type: "number",
+ transform: unsignedTransformation("size")
+ },
+ {
+ field: "startBit",
+ title: signal =>
+ signal.isLittleEndian ? "Least significant bit" : "Most significant bit",
+ type: "number",
+ transform: unsignedTransformation("startBit")
+ },
+ {
+ field: "isLittleEndian",
+ title: "Endianness",
+ type: "option",
+ options: {
+ options: ["Little", "Big"],
+ optionValues: { Little: true, Big: false }
+ },
+ transform: (isLittleEndian, signal) => {
+ if (signal.isLittleEndian !== isLittleEndian) {
+ const { startBit } = signal;
+
+ if (isLittleEndian) {
+ // big endian -> little endian
+ const startByte = Math.floor(signal.startBit / 8),
+ endByte = Math.floor((signal.startBit - signal.size + 1) / 8);
+
+ if (startByte === endByte) {
+ signal.startBit = signal.startBit - signal.size + 1;
+ } else {
+ signal.startBit = DbcUtils.matrixBitNumber(startBit);
+ }
+ } else {
+ // little endian -> big endian
+ const startByte = Math.floor(signal.startBit / 8),
+ endByte = Math.floor((signal.startBit + signal.size - 1) / 8);
+
+ if (startByte === endByte) {
+ signal.startBit = signal.startBit + signal.size - 1;
+ } else {
+ signal.startBit = DbcUtils.bigEndianBitIndex(startBit);
+ }
+ }
+ signal.isLittleEndian = isLittleEndian;
+ }
+ return signal;
+ }
+ },
+ {
+ field: "isSigned",
+ title: "Sign",
+ type: "option",
+ options: {
+ options: ["Signed", "Unsigned"],
+ optionValues: { Signed: true, Unsigned: false }
+ }
+ },
+ {
+ field: "factor",
+ title: "Factor",
+ type: "number"
+ },
+ {
+ field: "offset",
+ title: "Offset",
+ type: "number"
+ },
+ {
+ field: "unit",
+ title: "Unit",
+ type: "string"
+ },
+ {
+ field: "comment",
+ title: "Comment",
+ type: "string"
+ },
+ {
+ field: "min",
+ title: "Minimum value",
+ type: "number"
+ },
+ {
+ field: "max",
+ title: "Maximum value",
+ type: "number"
+ }
+];
diff --git a/src/components/SignalLegendEntry/Field.js b/src/components/SignalLegendEntry/Field.js
new file mode 100644
index 0000000..68351fd
--- /dev/null
+++ b/src/components/SignalLegendEntry/Field.js
@@ -0,0 +1,13 @@
+import React, { Component } from "react";
+
+export default class Field extends Component {
+ render() {
+ const { title, htmlFor, children } = this.props;
+ return (
+
+
+ {children}
+
+ );
+ }
+}
diff --git a/src/components/SignalLegendEntry/SignalForm.js b/src/components/SignalLegendEntry/SignalForm.js
new file mode 100644
index 0000000..d663e14
--- /dev/null
+++ b/src/components/SignalLegendEntry/SignalForm.js
@@ -0,0 +1,197 @@
+import React from "react";
+
+import Field from "./Field";
+import FIELDS from "./FIELDS";
+import { swapKeysAndValues } from "../../utils/object";
+
+export default ({
+ signal,
+ onSignalRemove,
+ isExpanded,
+ getSignalEdited,
+ update
+}) => {
+ return (
+
+ {FIELDS.map(field => {
+ // console.log(field, getSignalEdited(field.field))
+ return (
+
+
+
+ );
+ })}
+
+
+
+
+ );
+};
+
+const NumberField = ({
+ fieldSpec,
+ signal,
+ isExpanded,
+ signalEdited,
+ updateField
+}) => {
+ const { field, title } = fieldSpec;
+ const htmlFor = `${signal.name}_${field}`;
+ let valueCol;
+
+ if (isExpanded) {
+ let value = signalEdited;
+ if (value !== "") {
+ let num = Number(value);
+ value = isNaN(num) ? "" : num;
+ }
+ valueCol = (
+ {
+ updateField(fieldSpec, e.target.value);
+ }}
+ />
+ );
+ } else {
+ let value = signal[field];
+ valueCol = {value};
+ }
+ return (
+
+ {valueCol}
+
+ );
+};
+
+const StringField = ({
+ fieldSpec,
+ signal,
+ isExpanded,
+ signalEdited,
+ updateField
+}) => {
+ const { field, title } = fieldSpec;
+ const htmlFor = `${signal.name}_${field}`;
+ let valueCol;
+ if (isExpanded) {
+ valueCol = (
+ {
+ updateField(fieldSpec, e.target.value);
+ }}
+ />
+ );
+ } else {
+ valueCol = {signal[field]};
+ }
+
+ return (
+
+ {valueCol}
+
+ );
+};
+
+const OptionField = ({
+ fieldSpec,
+ signal,
+ isExpanded,
+ signalEdited,
+ updateField
+}) => {
+ let valueCol;
+ const { field, title } = fieldSpec;
+ const htmlFor = `${signal.name}_${field}`;
+ const { options, optionValues } = fieldSpec.options;
+ let valueOptions = swapKeysAndValues(optionValues);
+
+ if (isExpanded) {
+ const optionEles = options.map(opt => (
+
+ ));
+ valueCol = (
+
+ );
+ } else {
+ valueCol = {valueOptions[signal[field]]};
+ }
+
+ return (
+
+ {valueCol}
+
+ );
+};
+
+const FieldNode = ({ field, signal, isExpanded, signalEdited, update }) => {
+ switch (field.type) {
+ case "number":
+ return (
+
+ );
+ case "option":
+ return (
+
+ );
+ case "string":
+ return (
+
+ );
+ default:
+ return undefined;
+ }
+};
diff --git a/src/components/SignalLegendEntry/index.js b/src/components/SignalLegendEntry/index.js
new file mode 100644
index 0000000..ec1fe55
--- /dev/null
+++ b/src/components/SignalLegendEntry/index.js
@@ -0,0 +1,151 @@
+// SignalLegendEntry.js
+
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import cx from "classnames";
+
+import Signal from "../../models/can/signal";
+import SignalForm from "./SignalForm";
+import ColorBar from "./ColorBar";
+
+export default class SignalLegendEntry extends Component {
+ static propTypes = {
+ signal: PropTypes.instanceOf(Signal).isRequired,
+ isHighlighted: PropTypes.bool,
+ onSignalHover: PropTypes.func,
+ onSignalHoverEnd: PropTypes.func,
+ onTentativeSignalChange: PropTypes.func,
+ onSignalChange: PropTypes.func,
+ onSignalRemove: PropTypes.func,
+ onSignalPlotChange: PropTypes.func,
+ toggleExpandSignal: PropTypes.func,
+ isPlotted: PropTypes.bool,
+ isExpanded: PropTypes.bool
+ };
+
+ static fieldSpecForName = name => {
+ return SignalLegendEntry.fields.find(field => field.field === name);
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ signalEdited: Object.assign(Object.create(props.signal), props.signal)
+ };
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (!nextProps.signal.equals(this.props.signal)) {
+ this.setState({
+ signalEdited: Object.assign(
+ Object.create(nextProps.signal),
+ nextProps.signal
+ )
+ });
+ }
+ }
+
+ updateField = (fieldSpec, value) => {
+ let { signalEdited } = this.state;
+ const { signal } = this.props;
+
+ if (fieldSpec.transform) {
+ signalEdited = fieldSpec.transform(value, signalEdited);
+ } else {
+ signalEdited[fieldSpec.field] = value;
+ }
+
+ // Save entire signal while editing
+ this.setState({ signalEdited });
+ const signalCopy = Object.assign(Object.create(signal), signal);
+ Object.entries(signalEdited).forEach(([field, value]) => {
+ signalCopy[field] = value;
+ });
+ this.props.onSignalChange(signalCopy, signal);
+ };
+
+ toggleEditing = e => {
+ let { signalEdited } = this.state;
+ const { signal, isExpanded } = this.props;
+ const signalCopy = Object.assign(Object.create(signal), signal);
+
+ if (isExpanded) {
+ // Finished editing, save changes & reset intermediate
+ // signalEdited state.
+ Object.entries(signalEdited).forEach(([field, value]) => {
+ const fieldSpec = SignalLegendEntry.fieldSpecForName(field);
+
+ if (
+ fieldSpec &&
+ fieldSpec.type === "number" &&
+ isNaN(parseInt(value, 10))
+ ) {
+ value = 0;
+ }
+
+ signalCopy[field] = value;
+ });
+ this.props.onSignalChange(signalCopy, signal);
+ } else {
+ signalEdited = signalCopy;
+ }
+
+ // Expand and enable signal editing
+ this.setState({
+ signalEdited
+ });
+ this.props.toggleExpandSignal(signal);
+ e.stopPropagation();
+ };
+
+ toggleSignalPlot = e => {
+ const { signal, isPlotted } = this.props;
+ e.preventDefault();
+ this.props.onSignalPlotChange(!isPlotted, signal.uid);
+ };
+
+ getSignalEdited = field => {
+ return this.state.signalEdited[field];
+ };
+ render() {
+ const { signal, isHighlighted, color, isPlotted, isExpanded } = this.props;
+ const expandedEntryClass = isExpanded ? "is-expanded" : null;
+ const plottedButtonClass = isPlotted ? "button" : "button--alpha";
+ return (
+ this.props.onSignalHover(signal)}
+ onMouseLeave={() => this.props.onSignalHoverEnd(signal)}
+ >
+
+
+
+ {signal.name}
+
+
+
+
+
+
+ {isExpanded && (
+
+ )}
+
+
+ );
+ }
+}