Skip to content

Commit

Permalink
feat(xod-client, xod-client-browser, xod-client-electron): add UI for…
Browse files Browse the repository at this point in the history
… sending pulses during debug sessions through tweak-pulse nodes
  • Loading branch information
evgenykochetkov committed Feb 27, 2019
1 parent a4fe46a commit 2aa2716
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions packages/xod-client/src/core/styles/components/Inspector.scss
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@
}
}

.inspectorButton {
box-sizing: border-box;
line-height: 16px;
padding: 5px 4px;
}

.Widget {
margin: 6px 0;
overflow: hidden;
Expand Down Expand Up @@ -215,6 +221,7 @@

.inspector-input-wrapper,
.inspectorTextInput,
.inspectorButton,
.inspectorSelectInput {
float: right;
width: 120px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions packages/xod-client/src/editor/actionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
12 changes: 12 additions & 0 deletions packages/xod-client/src/editor/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
})
);
};
21 changes: 19 additions & 2 deletions packages/xod-client/src/editor/components/Inspector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,19 @@ const renderSelectedComment = () => (
<InspectorMessage text="Comments do not have any properties." />
);
const renderSelectedNode = R.curry(
(onPropUpdate, onNodeSpecializationChanged, selection) => (
(
onPropUpdate,
onNodeSpecializationChanged,
onSendTweakPulse,
isDebugSession,
selection
) => (
<NodeInspector
node={selection[0].data}
onPropUpdate={onPropUpdate}
onNodeSpecializationChanged={onNodeSpecializationChanged}
onSendTweakPulse={onSendTweakPulse}
isDebugSession={isDebugSession}
/>
)
);
Expand Down Expand Up @@ -97,17 +105,24 @@ const Inspector = ({
autohide,
selection,
currentPatch,
isDebugSession,
onPropUpdate,
onNodeSpecializationChanged,
onPatchDescriptionUpdate,
onSendTweakPulse,
}) => {
const inspectorContent = R.cond([
[isMany, renderSelectedManyElements],
[isSingleLink, renderSelectedLink],
[isSingleComment, renderSelectedComment],
[
isSingleNode,
renderSelectedNode(onPropUpdate, onNodeSpecializationChanged),
renderSelectedNode(
onPropUpdate,
onNodeSpecializationChanged,
onSendTweakPulse,
isDebugSession
),
],
[
isPatchSelected(currentPatch),
Expand All @@ -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 = {
Expand Down
29 changes: 27 additions & 2 deletions packages/xod-client/src/editor/components/NodeInspector.jsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -10,6 +11,7 @@ import {
Widget,
HintWidget,
NodeSpecializationWidget,
PulseTweakWidget,
getNodeWidgetConfig,
} from './inspectorWidgets';

Expand All @@ -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);
Expand Down Expand Up @@ -58,7 +72,16 @@ const NodeInspector = ({ node, onPropUpdate, onNodeSpecializationChanged }) => {

{DeadNodeMessage}

<PinWidgetsGroup node={node} onPropUpdate={onPropUpdate} />
<ul>
{isDebugSession && isTweakPulseNode(node) ? (
<PulseTweakWidget
onSendTweakPulse={onSendTweakPulse}
nodeId={nodeId}
/>
) : (
<PinWidgetsGroup node={node} onPropUpdate={onPropUpdate} />
)}
</ul>

<Widget
{...getNodeWidgetConfig(WIDGET_TYPE.LABEL)}
Expand Down Expand Up @@ -90,6 +113,8 @@ NodeInspector.propTypes = {
node: sanctuaryPropType(RenderableNode),
onPropUpdate: PropTypes.func.isRequired,
onNodeSpecializationChanged: PropTypes.func.isRequired,
isDebugSession: PropTypes.bool.isRequired,
onSendTweakPulse: PropTypes.func.isRequired,
};

export default NodeInspector;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Widget, getNodeWidgetConfig } from './inspectorWidgets';

const PinWidgetsGroup = ({ node, onPropUpdate }) =>
R.compose(
widgets => <ul>{widgets}</ul>,
widgets => <React.Fragment>{widgets}</React.Fragment>,
R.map(renderablePin => {
const widgetProps = R.applySpec({
entityId: R.prop('nodeId'),
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<li>
<PinWidget
elementId="pulse-tweak"
label="OUT"
dataType={XP.PIN_TYPE.PULSE}
direction={XP.PIN_DIRECTION.OUTPUT}
isBindable
isConnected
>
<button
className="Button inspectorButton"
onClick={this.handleClick}
>
Pulse
</button>
</PinWidget>
</li>
);
}
}

PulseTweakWidget.propTypes = {
nodeId: PT.string.isRequired,
onSendTweakPulse: PT.func.isRequired,
};

export default PulseTweakWidget;
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ PinWidget.propTypes = {

PinWidget.defaultProps = {
children: null,
isLastVariadicGroup: false,
};

export default PinWidget;
7 changes: 7 additions & 0 deletions packages/xod-client/src/editor/containers/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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}
/>
</FocusTrap>
);
Expand Down Expand Up @@ -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 */
Expand All @@ -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,
};
Expand All @@ -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(
Expand All @@ -272,6 +278,7 @@ const mapDispatchToProps = dispatch => ({
resizePanels: EditorActions.resizePanels,
togglePanel: EditorActions.togglePanel,
setFocusedArea: EditorActions.setFocusedArea,
sendTweakPulse: EditorActions.sendTweakPulse,
},
dispatch
),
Expand Down
13 changes: 11 additions & 2 deletions packages/xod-client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 => (
<RegularNodeBody
Expand Down

0 comments on commit 2aa2716

Please sign in to comment.