diff --git a/packages/xod-client-electron/src/debugger/sendToSerialMiddleware.js b/packages/xod-client-electron/src/debugger/sendToSerialMiddleware.js
index af5a6be6f..3aac53f2d 100644
--- a/packages/xod-client-electron/src/debugger/sendToSerialMiddleware.js
+++ b/packages/xod-client-electron/src/debugger/sendToSerialMiddleware.js
@@ -17,10 +17,10 @@ export default ({ getState }) => next => action => {
ipcRenderer.send(DEBUG_SERIAL_SEND, action.payload);
}
- if (
- action.type === client.NODE_UPDATE_PROPERTY &&
- client.isSerialDebugRunning(state)
- ) {
+ const isTweakActionType =
+ action.type === client.NODE_UPDATE_PROPERTY ||
+ action.type === client.TWEAK_PULSE_SENT;
+ if (isTweakActionType && client.isSerialDebugRunning(state)) {
const { id: nodeId, value, patchPath } = action.payload;
const nodeType = R.compose(
XP.getNodeType,
diff --git a/packages/xod-client/src/core/styles/components/Inspector.scss b/packages/xod-client/src/core/styles/components/Inspector.scss
index eb99212c9..c17d56c33 100644
--- a/packages/xod-client/src/core/styles/components/Inspector.scss
+++ b/packages/xod-client/src/core/styles/components/Inspector.scss
@@ -132,6 +132,12 @@
}
}
+.inspectorButton {
+ box-sizing: border-box;
+ line-height: 16px;
+ padding: 5px 4px;
+}
+
.Widget {
margin: 6px 0;
overflow: hidden;
@@ -215,6 +221,7 @@
.inspector-input-wrapper,
.inspectorTextInput,
+ .inspectorButton,
.inspectorSelectInput {
float: right;
width: 120px;
diff --git a/packages/xod-client/src/debugger/sendToSimulationSerialMiddleware.js b/packages/xod-client/src/debugger/sendToSimulationSerialMiddleware.js
index 4de8ad22f..7ccd33db0 100644
--- a/packages/xod-client/src/debugger/sendToSimulationSerialMiddleware.js
+++ b/packages/xod-client/src/debugger/sendToSimulationSerialMiddleware.js
@@ -10,12 +10,15 @@ import {
import * as editorSelectors from '../editor/selectors';
import { NODE_UPDATE_PROPERTY } from '../project/actionTypes';
+import { TWEAK_PULSE_SENT } from '../editor/actionTypes';
export default ({ getState }) => next => action => {
const state = getState();
const result = next(action);
- if (action.type === NODE_UPDATE_PROPERTY && isSimulationRunning(state)) {
+ const isTweakActionType =
+ action.type === NODE_UPDATE_PROPERTY || action.type === TWEAK_PULSE_SENT;
+ if (isTweakActionType && isSimulationRunning(state)) {
const { id: nodeId, value, patchPath } = action.payload;
const nodeType = R.compose(
XP.getNodeType,
diff --git a/packages/xod-client/src/editor/actionTypes.js b/packages/xod-client/src/editor/actionTypes.js
index 6ab748816..86304bba4 100644
--- a/packages/xod-client/src/editor/actionTypes.js
+++ b/packages/xod-client/src/editor/actionTypes.js
@@ -62,3 +62,5 @@ export const SIMULATION_COMPILED = 'SIMULATION_COMPILED';
export const SIMULATION_LAUNCHED = 'SIMULATION_LAUNCHED';
export const SIMULATION_ABORT = 'SIMULATION_ABORT';
export const SIMULATION_ERROR = 'SIMULATION_ERROR';
+
+export const TWEAK_PULSE_SENT = 'TWEAK_PULSE_SENT';
diff --git a/packages/xod-client/src/editor/actions.js b/packages/xod-client/src/editor/actions.js
index 144fbda79..6d5ee7a77 100644
--- a/packages/xod-client/src/editor/actions.js
+++ b/packages/xod-client/src/editor/actions.js
@@ -879,3 +879,15 @@ export const runSimulation = (simulationPatchPath, nodeIdsMap, code) => (
});
});
};
+
+export const sendTweakPulse = tweakNodeId => (dispatch, getState) => {
+ Selectors.getCurrentPatchPath(getState()).map(patchPath =>
+ dispatch({
+ type: ActionType.TWEAK_PULSE_SENT,
+ payload: {
+ patchPath,
+ id: tweakNodeId,
+ },
+ })
+ );
+};
diff --git a/packages/xod-client/src/editor/components/Inspector.jsx b/packages/xod-client/src/editor/components/Inspector.jsx
index 27dd06564..027021c09 100644
--- a/packages/xod-client/src/editor/components/Inspector.jsx
+++ b/packages/xod-client/src/editor/components/Inspector.jsx
@@ -49,11 +49,19 @@ const renderSelectedComment = () => (
);
const renderSelectedNode = R.curry(
- (onPropUpdate, onNodeSpecializationChanged, selection) => (
+ (
+ onPropUpdate,
+ onNodeSpecializationChanged,
+ onSendTweakPulse,
+ isDebugSession,
+ selection
+ ) => (
)
);
@@ -97,9 +105,11 @@ const Inspector = ({
autohide,
selection,
currentPatch,
+ isDebugSession,
onPropUpdate,
onNodeSpecializationChanged,
onPatchDescriptionUpdate,
+ onSendTweakPulse,
}) => {
const inspectorContent = R.cond([
[isMany, renderSelectedManyElements],
@@ -107,7 +117,12 @@ const Inspector = ({
[isSingleComment, renderSelectedComment],
[
isSingleNode,
- renderSelectedNode(onPropUpdate, onNodeSpecializationChanged),
+ renderSelectedNode(
+ onPropUpdate,
+ onNodeSpecializationChanged,
+ onSendTweakPulse,
+ isDebugSession
+ ),
],
[
isPatchSelected(currentPatch),
@@ -134,9 +149,11 @@ Inspector.propTypes = {
autohide: PropTypes.bool.isRequired,
selection: sanctuaryPropType($.Array(RenderableSelection)),
currentPatch: sanctuaryPropType($Maybe(Patch)),
+ isDebugSession: PropTypes.bool.isRequired,
onPropUpdate: PropTypes.func.isRequired,
onNodeSpecializationChanged: PropTypes.func.isRequired,
onPatchDescriptionUpdate: PropTypes.func.isRequired,
+ onSendTweakPulse: PropTypes.func.isRequired,
};
Inspector.defaultProps = {
diff --git a/packages/xod-client/src/editor/components/NodeInspector.jsx b/packages/xod-client/src/editor/components/NodeInspector.jsx
index 6becf8e26..40881e2be 100644
--- a/packages/xod-client/src/editor/components/NodeInspector.jsx
+++ b/packages/xod-client/src/editor/components/NodeInspector.jsx
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
+import R from 'ramda';
import * as XP from 'xod-project';
import { WIDGET_TYPE } from '../constants';
@@ -10,6 +11,7 @@ import {
Widget,
HintWidget,
NodeSpecializationWidget,
+ PulseTweakWidget,
getNodeWidgetConfig,
} from './inspectorWidgets';
@@ -19,7 +21,19 @@ import { getUtmSiteUrl } from '../../utils/urls';
import * as MESSAGES from '../messages';
-const NodeInspector = ({ node, onPropUpdate, onNodeSpecializationChanged }) => {
+const isTweakPulseNode = R.compose(
+ nodeType =>
+ XP.isTweakPath(nodeType) && XP.getTweakType(nodeType) === XP.PIN_TYPE.PULSE,
+ XP.getNodeType
+);
+
+const NodeInspector = ({
+ node,
+ isDebugSession,
+ onPropUpdate,
+ onNodeSpecializationChanged,
+ onSendTweakPulse,
+}) => {
const type = XP.getNodeType(node);
const baseName = XP.getBaseName(type);
const nodeId = XP.getNodeId(node);
@@ -58,7 +72,16 @@ const NodeInspector = ({ node, onPropUpdate, onNodeSpecializationChanged }) => {
{DeadNodeMessage}
-
+
+ {isDebugSession && isTweakPulseNode(node) ? (
+
+ ) : (
+
+ )}
+
R.compose(
- widgets => ,
+ widgets => {widgets},
R.map(renderablePin => {
const widgetProps = R.applySpec({
entityId: R.prop('nodeId'),
diff --git a/packages/xod-client/src/editor/components/inspectorWidgets/PulseTweakWidget.jsx b/packages/xod-client/src/editor/components/inspectorWidgets/PulseTweakWidget.jsx
new file mode 100644
index 000000000..a0b1ccaf7
--- /dev/null
+++ b/packages/xod-client/src/editor/components/inspectorWidgets/PulseTweakWidget.jsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import PT from 'prop-types';
+import * as XP from 'xod-project';
+
+import PinWidget from './pinWidgets/PinWidget';
+
+class PulseTweakWidget extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleClick = this.handleClick.bind(this);
+ }
+
+ handleClick() {
+ this.props.onSendTweakPulse(this.props.nodeId);
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ );
+ }
+}
+
+PulseTweakWidget.propTypes = {
+ nodeId: PT.string.isRequired,
+ onSendTweakPulse: PT.func.isRequired,
+};
+
+export default PulseTweakWidget;
diff --git a/packages/xod-client/src/editor/components/inspectorWidgets/index.js b/packages/xod-client/src/editor/components/inspectorWidgets/index.js
index 24922c20c..2b950ee02 100644
--- a/packages/xod-client/src/editor/components/inspectorWidgets/index.js
+++ b/packages/xod-client/src/editor/components/inspectorWidgets/index.js
@@ -148,6 +148,7 @@ export {
} from './pinWidgets/DisabledInputWidget';
export { default as DescriptionWidget } from './DescriptionWidget';
export { default as LabelWidget } from './LabelWidget';
+export { default as PulseTweakWidget } from './PulseTweakWidget';
export {
default as NodeSpecializationWidget,
} from './NodeSpecializationWidget';
diff --git a/packages/xod-client/src/editor/components/inspectorWidgets/pinWidgets/PinWidget.jsx b/packages/xod-client/src/editor/components/inspectorWidgets/pinWidgets/PinWidget.jsx
index c8903b2a9..7274bb140 100644
--- a/packages/xod-client/src/editor/components/inspectorWidgets/pinWidgets/PinWidget.jsx
+++ b/packages/xod-client/src/editor/components/inspectorWidgets/pinWidgets/PinWidget.jsx
@@ -80,6 +80,7 @@ PinWidget.propTypes = {
PinWidget.defaultProps = {
children: null,
+ isLastVariadicGroup: false,
};
export default PinWidget;
diff --git a/packages/xod-client/src/editor/containers/Sidebar.jsx b/packages/xod-client/src/editor/containers/Sidebar.jsx
index a783d28c7..e52f45687 100644
--- a/packages/xod-client/src/editor/containers/Sidebar.jsx
+++ b/packages/xod-client/src/editor/containers/Sidebar.jsx
@@ -22,6 +22,7 @@ import * as EditorSelectors from '../selectors';
import * as ProjectActions from '../../project/actions';
import * as ProjectSelectors from '../../project/selectors';
import * as UserSelectors from '../../user/selectors';
+import * as DebuggerSelectors from '../../debugger/selectors';
import { RenderableSelection } from '../../types';
import sanctuaryPropType from '../../utils/sanctuaryPropType';
import { SIDEBAR_IDS, PANEL_IDS, FOCUS_AREAS } from '../constants';
@@ -147,6 +148,8 @@ class Sidebar extends React.Component {
this.props.actions.changeNodeSpecialization
}
onPatchDescriptionUpdate={this.props.actions.updatePatchDescription}
+ onSendTweakPulse={this.props.actions.sendTweakPulse}
+ isDebugSession={this.props.isDebugSession}
/>
);
@@ -237,6 +240,7 @@ Sidebar.propTypes = {
windowSize: PropTypes.object.isRequired,
selection: sanctuaryPropType($.Array(RenderableSelection)),
currentPatch: sanctuaryPropType($Maybe(XP.Patch)),
+ isDebugSession: PropTypes.bool.isRequired,
panels: PropTypes.objectOf(
PropTypes.shape({
/* eslint-disable react/no-unused-prop-types */
@@ -253,6 +257,7 @@ Sidebar.propTypes = {
resizePanels: PropTypes.func.isRequired,
togglePanel: PropTypes.func.isRequired,
setFocusedArea: PropTypes.func.isRequired,
+ sendTweakPulse: PropTypes.func.isRequired,
}),
userAuthorised: PropTypes.bool.isRequired,
};
@@ -262,6 +267,7 @@ const mapStateToProps = R.applySpec({
currentPatch: ProjectSelectors.getCurrentPatch,
panels: EditorSelectors.getAllPanelsSettings,
userAuthorised: UserSelectors.isAuthorized,
+ isDebugSession: DebuggerSelectors.isDebugSession,
});
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators(
@@ -272,6 +278,7 @@ const mapDispatchToProps = dispatch => ({
resizePanels: EditorActions.resizePanels,
togglePanel: EditorActions.togglePanel,
setFocusedArea: EditorActions.setFocusedArea,
+ sendTweakPulse: EditorActions.sendTweakPulse,
},
dispatch
),
diff --git a/packages/xod-client/src/index.js b/packages/xod-client/src/index.js
index b0eec5dd0..3a98a2a69 100644
--- a/packages/xod-client/src/index.js
+++ b/packages/xod-client/src/index.js
@@ -26,7 +26,11 @@ import {
import { LOG_TAB_TYPE } from './debugger/constants';
import { MESSAGE_BUTTON_CLICKED } from './messages/actionTypes';
-import { TAB_CLOSE, INSTALL_LIBRARIES_COMPLETE } from './editor/actionTypes';
+import {
+ TAB_CLOSE,
+ INSTALL_LIBRARIES_COMPLETE,
+ TWEAK_PULSE_SENT,
+} from './editor/actionTypes';
import { SAVE_ALL, NODE_UPDATE_PROPERTY } from './project/actionTypes';
import * as EditorConstants from './editor/constants';
@@ -84,7 +88,11 @@ export { LOG_TAB_TYPE } from './debugger/constants';
export { MESSAGE_BUTTON_CLICKED } from './messages/actionTypes';
export { TAB_CLOSE, INSTALL_LIBRARIES_COMPLETE } from './editor/actionTypes';
-export { SAVE_ALL, NODE_UPDATE_PROPERTY } from './project/actionTypes';
+export {
+ SAVE_ALL,
+ NODE_UPDATE_PROPERTY,
+ TWEAK_PULSE_SENT,
+} from './project/actionTypes';
export {
SERIAL_SESSION_STARTED,
LINE_SENT_TO_SERIAL,
@@ -172,6 +180,7 @@ export default Object.assign(
TAB_CLOSE,
SAVE_ALL,
NODE_UPDATE_PROPERTY,
+ TWEAK_PULSE_SENT,
INSTALL_LIBRARIES_COMPLETE,
MESSAGE_BUTTON_CLICKED,
Messages: coreMessages,
diff --git a/packages/xod-client/src/project/components/nodeParts/ConstantNodeBody.jsx b/packages/xod-client/src/project/components/nodeParts/ConstantNodeBody.jsx
index af9b8e756..9448fbd06 100644
--- a/packages/xod-client/src/project/components/nodeParts/ConstantNodeBody.jsx
+++ b/packages/xod-client/src/project/components/nodeParts/ConstantNodeBody.jsx
@@ -7,7 +7,16 @@ import { noop } from 'xod-func-tools';
import RegularNodeBody from './RegularNodeBody';
export const getConstantValue = ({ pins }) =>
- R.compose(R.prop('value'), R.head, R.values)(pins);
+ R.compose(
+ R.ifElse(
+ // because for pulse nodes value will always be 'Never'
+ R.pipe(XP.getPinType, R.equals(XP.PIN_TYPE.PULSE)),
+ R.always(null),
+ R.prop('value')
+ ),
+ R.head,
+ R.values
+ )(pins);
const ConstantNodeBody = props => (