',{class:"red-ui-type-search-shade"}).appendTo("#main-container");
dialog = $("
",{id:"red-ui-type-search",class:"red-ui-search red-ui-type-search"}).appendTo("#main-container");
var searchDiv = $("
",{class:"red-ui-search-container"}).appendTo(dialog);
- searchInput = $('').attr("placeholder",RED._("search.addNode")).appendTo(searchDiv).searchBox({
+ searchInput = $('').attr("placeholder",RED._("search.addNode")).appendTo(searchDiv).searchBox({
delay: 50,
change: function() {
search($(this).val());
@@ -79,6 +79,19 @@ RED.typeSearch = (function() {
$(children[selected]).addClass('selected');
ensureSelectedIsVisible();
evt.preventDefault();
+ } else if ((evt.metaKey || evt.ctrlKey) && evt.keyCode === 13 ) {
+ // (ctrl or cmd) and enter
+ var index = Math.max(0,selected);
+ if (index < children.length) {
+ var n = $(children[index]).find(".red-ui-editableList-item-content").data('data');
+ typesUsed[n.type] = Date.now();
+ if (n.def.outputs === 0) {
+ confirm(n);
+ } else {
+ addCallback(n.type,true);
+ }
+ $("#red-ui-type-search-input").val("").keyup();
+ }
} else if (evt.keyCode === 13) {
// Enter
var index = Math.max(0,selected);
@@ -191,20 +204,27 @@ RED.typeSearch = (function() {
createDialog();
}
visible = true;
- setTimeout(function() {
- $(document).on('mousedown.type-search',handleMouseActivity);
- $(document).on('mouseup.type-search',handleMouseActivity);
- $(document).on('click.type-search',handleMouseActivity);
- },200);
} else {
dialog.hide();
searchResultsDiv.hide();
}
+ $(document).off('mousedown.type-search');
+ $(document).off('mouseup.type-search');
+ $(document).off('click.type-search');
+ setTimeout(function() {
+ $(document).on('mousedown.type-search',handleMouseActivity);
+ $(document).on('mouseup.type-search',handleMouseActivity);
+ $(document).on('click.type-search',handleMouseActivity);
+ },200);
+
refreshTypeList(opts);
addCallback = opts.add;
- closeCallback = opts.close;
+ cancelCallback = opts.cancel;
RED.events.emit("type-search:open");
//shade.show();
+ if ($("#main-container").height() - opts.y - 150 < 0) {
+ opts.y = opts.y - 235;
+ }
dialog.css({left:opts.x+"px",top:opts.y+"px"}).show();
searchResultsDiv.slideDown(300);
setTimeout(function() {
@@ -230,7 +250,6 @@ RED.typeSearch = (function() {
$(document).off('click.type-search');
}
}
-
function getTypeLabel(type, def) {
var label = type;
if (typeof def.paletteLabel !== "undefined") {
@@ -334,6 +353,7 @@ RED.typeSearch = (function() {
return {
show: show,
+ refresh: refreshTypeList,
hide: hide
};
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
index 6c8951b34..9b6415624 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
@@ -55,6 +55,7 @@ RED.view = (function() {
mouse_mode = 0,
moving_set = [],
lasso = null,
+ ghostNode = null,
showStatus = false,
lastClickNode = null,
dblClickPrimed = null,
@@ -650,10 +651,8 @@ RED.view = (function() {
mouse_mode = RED.state.PANNING;
mouse_position = [d3.event.pageX,d3.event.pageY]
scroll_position = [chart.scrollLeft(),chart.scrollTop()];
-
return;
}
-
if (!mousedown_node && !mousedown_link) {
selected_link = null;
updateSelection();
@@ -667,6 +666,16 @@ RED.view = (function() {
if (mouse_mode === 0 || mouse_mode === RED.state.QUICK_JOINING) {
if (d3.event.metaKey || d3.event.ctrlKey) {
point = d3.mouse(this);
+ var ox = point[0];
+ var oy = point[1];
+
+ if (RED.settings.get("editor").view['view-snap-grid']) {
+ // vis.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
+ point[0] = Math.round(point[0] / gridSize) * gridSize;
+ point[1] = Math.round(point[1] / gridSize) * gridSize;
+ // vis.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','blue')
+ }
+
d3.event.stopPropagation();
var mainPos = $("#main-container").position();
@@ -674,6 +683,24 @@ RED.view = (function() {
mouse_mode = RED.state.QUICK_JOINING;
$(window).on('keyup',disableQuickJoinEventHandler);
}
+ quickAddActive = true;
+
+ if (ghostNode) {
+ ghostNode.remove();
+ }
+ ghostNode = vis.append("g").attr('transform','translate('+(point[0] - node_width/2)+','+(point[1] - node_height/2)+')');
+ ghostNode.append("rect")
+ .attr("class","node_placeholder")
+ .attr("rx", 5)
+ .attr("ry", 5)
+ .attr("width",node_width)
+ .attr("height",node_height)
+ .attr("fill","none")
+ // var ghostLink = ghostNode.append("svg:path")
+ // .attr("class","link_link")
+ // .attr("d","M 0 "+(node_height/2)+" H "+(gridSize * -2))
+ // .attr("opacity",0);
+
var filter = undefined;
if (drag_lines.length > 0) {
if (drag_lines[0].virtualLink) {
@@ -683,106 +710,176 @@ RED.view = (function() {
} else {
filter = {output:true}
}
+
+ quickAddLink = {
+ node: drag_lines[0].node,
+ port: drag_lines[0].port,
+ portType: drag_lines[0].portType,
+ }
+ if (drag_lines[0].virtualLink) {
+ quickAddLink.virtualLink = true;
+ }
+ hideDragLines();
}
- quickAddActive = true;
+ var rebuildQuickAddLink = function() {
+ if (!quickAddLink) {
+ return;
+ }
+ if (!quickAddLink.el) {
+ quickAddLink.el = dragGroup.append("svg:path").attr("class", "drag_line");
+ }
+ var numOutputs = (quickAddLink.portType === PORT_TYPE_OUTPUT)?(quickAddLink.node.outputs || 1):1;
+ var sourcePort = quickAddLink.port;
+ var portY = -((numOutputs-1)/2)*13 +13*sourcePort;
+ var sc = (quickAddLink.portType === PORT_TYPE_OUTPUT)?1:-1;
+ quickAddLink.el.attr("d",generateLinkPath(quickAddLink.node.x+sc*quickAddLink.node.w/2,quickAddLink.node.y+portY,point[0]-sc*node_width/2,point[1],sc));
+ }
+ if (quickAddLink) {
+ rebuildQuickAddLink();
+ }
+
+
+ var lastAddedX;
+ var lastAddedWidth;
+
RED.typeSearch.show({
- x:d3.event.clientX-mainPos.left-node_width/2,
- y:d3.event.clientY-mainPos.top-node_height/2,
+ x:d3.event.clientX-mainPos.left-node_width/2 - (ox-point[0]),
+ y:d3.event.clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
filter: filter,
cancel: function() {
+ if (quickAddLink) {
+ if (quickAddLink.el) {
+ quickAddLink.el.remove();
+ }
+ quickAddLink = null;
+ }
quickAddActive = false;
+ if (ghostNode) {
+ ghostNode.remove();
+ }
resetMouseVars();
+ updateSelection();
+ hideDragLines();
+ redraw();
},
- add: function(type) {
- quickAddActive = false;
+ add: function(type,keepAdding) {
var result = addNode(type);
if (!result) {
return;
}
+ if (keepAdding) {
+ mouse_mode = RED.state.QUICK_JOINING;
+ }
+
var nn = result.node;
var historyEvent = result.historyEvent;
nn.x = point[0];
nn.y = point[1];
-
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel;
}
+ if (quickAddLink) {
+ var drag_line = quickAddLink;
+ var src = null,dst,src_port;
+ if (drag_line.portType === PORT_TYPE_OUTPUT && (nn.inputs > 0 || drag_line.virtualLink) ) {
+ src = drag_line.node;
+ src_port = drag_line.port;
+ dst = nn;
+ } else if (drag_line.portType === PORT_TYPE_INPUT && (nn.outputs > 0 || drag_line.virtualLink)) {
+ src = nn;
+ dst = drag_line.node;
+ src_port = 0;
+ }
- if (mouse_mode === RED.state.QUICK_JOINING || quickAddLink) {
- if (quickAddLink || drag_lines.length > 0) {
- var drag_line = quickAddLink||drag_lines[0];
- var src = null,dst,src_port;
- if (drag_line.portType === PORT_TYPE_OUTPUT && (nn.inputs > 0 || drag_line.virtualLink) ) {
- src = drag_line.node;
- src_port = drag_line.port;
- dst = nn;
- } else if (drag_line.portType === PORT_TYPE_INPUT && (nn.outputs > 0 || drag_line.virtualLink)) {
- src = nn;
- dst = drag_line.node;
- src_port = 0;
- }
-
- if (src !== null) {
- if (drag_line.virtualLink) {
- historyEvent = {
- t:'multi',
- events: [historyEvent]
- }
- var oldSrcLinks = $.extend(true,{},{v:src.links}).v
- var oldDstLinks = $.extend(true,{},{v:dst.links}).v
- src.links.push(dst.id);
- dst.links.push(src.id);
- src.dirty = true;
- dst.dirty = true;
-
- historyEvent.events.push({
- t:'edit',
- node: src,
- dirty: RED.nodes.dirty(),
- changed: src.changed,
- changes: {
- links:oldSrcLinks
- }
- });
- historyEvent.events.push({
- t:'edit',
- node: dst,
- dirty: RED.nodes.dirty(),
- changed: dst.changed,
- changes: {
- links:oldDstLinks
- }
- });
- src.changed = true;
- dst.changed = true;
- } else {
- var link = {source: src, sourcePort:src_port, target: dst};
- RED.nodes.addLink(link);
- historyEvent.links = [link];
+ if (src !== null) {
+ // Joining link nodes via virual wires. Need to update
+ // the src and dst links property
+ if (drag_line.virtualLink) {
+ historyEvent = {
+ t:'multi',
+ events: [historyEvent]
}
- hideDragLines();
- if (!quickAddLink && drag_line.portType === PORT_TYPE_OUTPUT && nn.outputs > 0) {
+ var oldSrcLinks = $.extend(true,{},{v:src.links}).v
+ var oldDstLinks = $.extend(true,{},{v:dst.links}).v
+ src.links.push(dst.id);
+ dst.links.push(src.id);
+ src.dirty = true;
+ dst.dirty = true;
+
+ historyEvent.events.push({
+ t:'edit',
+ node: src,
+ dirty: RED.nodes.dirty(),
+ changed: src.changed,
+ changes: {
+ links:oldSrcLinks
+ }
+ });
+ historyEvent.events.push({
+ t:'edit',
+ node: dst,
+ dirty: RED.nodes.dirty(),
+ changed: dst.changed,
+ changes: {
+ links:oldDstLinks
+ }
+ });
+ src.changed = true;
+ dst.changed = true;
+ } else {
+ var link = {source: src, sourcePort:src_port, target: dst};
+ RED.nodes.addLink(link);
+ historyEvent.links = [link];
+ }
+ if (!keepAdding) {
+ quickAddLink.el.remove();
+ quickAddLink = null;
+ if (mouse_mode === RED.state.QUICK_JOINING) {
+ if (drag_line.portType === PORT_TYPE_OUTPUT && nn.outputs > 0) {
+ showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
+ } else if (!quickAddLink && drag_line.portType === PORT_TYPE_INPUT && nn.inputs > 0) {
+ showDragLines([{node:nn,port:0,portType:PORT_TYPE_INPUT}]);
+ } else {
+ resetMouseVars();
+ }
+ }
+ } else {
+ quickAddLink.node = nn;
+ quickAddLink.port = 0;
+ }
+ } else {
+ hideDragLines();
+ resetMouseVars();
+ }
+ } else {
+ if (!keepAdding) {
+ if (mouse_mode === RED.state.QUICK_JOINING) {
+ if (nn.outputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
- } else if (!quickAddLink && drag_line.portType === PORT_TYPE_INPUT && nn.inputs > 0) {
+ } else if (nn.inputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_INPUT}]);
} else {
resetMouseVars();
}
- } else {
- hideDragLines();
- resetMouseVars();
}
} else {
if (nn.outputs > 0) {
- showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
+ quickAddLink = {
+ node: nn,
+ port: 0,
+ portType: PORT_TYPE_OUTPUT
+ }
} else if (nn.inputs > 0) {
- showDragLines([{node:nn,port:0,portType:PORT_TYPE_INPUT}]);
+ quickAddLink = {
+ node: nn,
+ port: 0,
+ portType: PORT_TYPE_INPUT
+ }
} else {
resetMouseVars();
}
}
- quickAddLink = null;
}
RED.history.push(historyEvent);
@@ -796,6 +893,37 @@ RED.view = (function() {
updateActiveNodes();
updateSelection();
redraw();
+ // At this point the newly added node will have a real width,
+ // so check if the position needs nudging
+ if (lastAddedX !== undefined) {
+ var lastNodeRHEdge = lastAddedX + lastAddedWidth/2;
+ var thisNodeLHEdge = nn.x - nn.w/2;
+ var gap = thisNodeLHEdge - lastNodeRHEdge;
+ if (gap != gridSize *2) {
+ nn.x = nn.x + gridSize * 2 - gap;
+ nn.dirty = true;
+ nn.x = Math.ceil(nn.x / gridSize) * gridSize;
+ redraw();
+ }
+ }
+ if (keepAdding) {
+ if (lastAddedX === undefined) {
+ // ghostLink.attr("opacity",1);
+ setTimeout(function() {
+ RED.typeSearch.refresh({filter:{input:true}});
+ },100);
+ }
+
+ lastAddedX = nn.x;
+ lastAddedWidth = nn.w;
+
+ point[0] = nn.x + nn.w/2 + node_width/2 + gridSize * 2;
+ ghostNode.attr('transform','translate('+(point[0] - node_width/2)+','+(point[1] - node_height/2)+')');
+ rebuildQuickAddLink();
+ } else {
+ quickAddActive = false;
+ ghostNode.remove();
+ }
}
});
@@ -850,7 +978,6 @@ RED.view = (function() {
mouse_position = d3.touches(this)[0]||d3.mouse(this);
-
if (lasso) {
var ox = parseInt(lasso.attr("ox"));
var oy = parseInt(lasso.attr("oy"));
@@ -935,7 +1062,7 @@ RED.view = (function() {
redraw();
mouse_mode = RED.state.JOINING;
}
- } else if (mousedown_node) {
+ } else if (mousedown_node && !quickAddLink) {
showDragLines([{node:mousedown_node,port:mousedown_port_index,portType:mousedown_port_type}]);
}
selected_link = null;
@@ -948,7 +1075,6 @@ RED.view = (function() {
var portY = -((numOutputs-1)/2)*13 +13*sourcePort;
var sc = (drag_line.portType === PORT_TYPE_OUTPUT)?1:-1;
-
drag_line.el.attr("d",generateLinkPath(drag_line.node.x+sc*drag_line.node.w/2,drag_line.node.y+portY,mousePos[0],mousePos[1],sc));
}
d3.event.preventDefault();
@@ -1139,7 +1265,7 @@ RED.view = (function() {
updateSelection();
lasso.remove();
lasso = null;
- } else if (mouse_mode == RED.state.DEFAULT && mousedown_link == null && !d3.event.ctrlKey&& !d3.event.metaKey ) {
+ } else if (mouse_mode == RED.state.DEFAULT && mousedown_link == null && !d3.event.ctrlKey && !d3.event.metaKey ) {
clearSelection();
updateSelection();
}
@@ -1616,9 +1742,6 @@ RED.view = (function() {
function disableQuickJoinEventHandler(evt) {
// Check for ctrl (all browsers), "Meta" (Chrome/FF), keyCode 91 (Safari)
if (evt.keyCode === 17 || evt.key === "Meta" || evt.keyCode === 91) {
- if (quickAddActive && drag_lines.length > 0) {
- quickAddLink = drag_lines[0];
- }
resetMouseVars();
hideDragLines();
redraw();
@@ -1643,7 +1766,6 @@ RED.view = (function() {
if (d3.event.ctrlKey || d3.event.metaKey) {
mouse_mode = RED.state.QUICK_JOINING;
showDragLines([{node:mousedown_node,port:mousedown_port_index,portType:mousedown_port_type}]);
- quickAddLink = null;
$(window).on('keyup',disableQuickJoinEventHandler);
}
}
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/flow.scss b/packages/node_modules/@node-red/editor-client/src/sass/flow.scss
index ecd95847f..26e7443df 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/flow.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/flow.scss
@@ -92,6 +92,14 @@
stroke-dasharray:10,4;
stroke: #f33;
}
+.node_placeholder {
+ stroke-dasharray:10,4;
+ stroke: #aaa;
+ fill: #eee;
+ opacity: 0.5;
+ stroke-width: 2;
+}
+
.tool_arrow {
stroke-width: 1;
stroke: #999;