diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json index fa347e6ea..ad985e785 100755 --- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json @@ -45,7 +45,8 @@ "rtl": "Right-to-left", "auto": "Contextual", "language": "Language", - "browserDefault": "Browser default" + "browserDefault": "Browser default", + "flowVertical": "Vertical flow" }, "sidebar": { "show": "Show sidebar" diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json index a6aab331d..d1d7dcefb 100755 --- a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json @@ -45,7 +45,8 @@ "rtl": "右から左", "auto": "文脈", "language": "表示言語", - "browserDefault": "ブラウザのデフォルト" + "browserDefault": "ブラウザのデフォルト", + "flowVertical": "縦フロー" }, "sidebar": { "show": "サイドバーを表示" diff --git a/packages/node_modules/@node-red/editor-client/locales/zh-CN/editor.json b/packages/node_modules/@node-red/editor-client/locales/zh-CN/editor.json index a45f37f66..3c23fc553 100644 --- a/packages/node_modules/@node-red/editor-client/locales/zh-CN/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/zh-CN/editor.json @@ -36,7 +36,8 @@ "defaultDir": "默认方向", "ltr": "从左到右", "rtl": "从右到左", - "auto": "上下文" + "auto": "上下文", + "flowVertical": "Vertical flow" }, "sidebar": { "show": "显示侧边栏" diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js b/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js index d2ef971b3..f80ac98d0 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js @@ -139,7 +139,14 @@ RED.palette = (function() { var labelElement = el.find(".red-ui-palette-label"); labelElement.html(lines).attr('dir', RED.text.bidi.resolveBaseTextDir(lines)); - el.find(".red-ui-palette-port").css({top:(multiLineNodeHeight/2-5)+"px"}); + if (RED.view.vertical()) { + el.find(".red-ui-palette-port").css({top:(multiLineNodeHeight/2-5)+"px", left: "55px"}); + el.find(".red-ui-palette-port-output").css({top:(multiLineNodeHeight-5)+"px", right: "55px"}); + el.find(".red-ui-palette-port-input").css({top: "-5px"}); + }else{ + el.find(".red-ui-palette-port").css({top:(multiLineNodeHeight/2-5)+"px"}); + // el.find(".palette_port_output").css({top:(multiLineNodeHeight/2-5)+"px", right: "-6px", left: "auto"}); + } var popOverContent; try { diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js b/packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js index 07ab12180..9e52bdbf3 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js @@ -133,7 +133,8 @@ RED.userSettings = (function() { { title: "menu.label.other", options: [ - {setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"} + {setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"}, + {setting:"view-flow-vertical",label:"menu.label.view.flowVertical",toggle:true,default:false,onchange:RED.view.vertical} ] } ]; 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 old mode 100755 new mode 100644 index 0967c630e..87dd69738 --- 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 @@ -44,6 +44,7 @@ RED.view = (function() { var gridSize = 20; var snapGrid = false; + var vertical = false; var activeSpliceLink; var spliceActive = false; @@ -595,6 +596,76 @@ RED.view = (function() { } } + function generateLinkPathV(origX,origY, destX, destY, sc) { + var dy = destY-origY; + var dx = destX-origX; + var delta = Math.sqrt(dy*dy+dx*dx); + var scale = lineCurveScale; + var scaleX = 0; + if (dy*sc > 0) { + if (delta < node_height) { + scale = 0.75-0.75*((node_height-delta)/node_height); + // scale += 2*(Math.min(5*node_height,Math.abs(dx))/(5*node_height)); + // if (Math.abs(dy) < 3*node_height) { + // scaleY = ((dy>0)?0.5:-0.5)*(((3*node_height)-Math.abs(dy))/(3*node_height))*(Math.min(node_height,Math.abs(dx))/(node_height)) ; + // } + } + } else { + scale = 0.4-0.2*(Math.max(0,(node_height-Math.min(Math.abs(dx),Math.abs(dy)))/node_height)); + } + if (dy*sc > 0) { + return "M "+origX+" "+origY+ + " C "+(origX+(node_width*scaleX))+" "+(origY+sc*scale*node_height)+" "+ + (destX-(node_width*scaleX))+" "+(destY-sc*scale*node_height)+" "+ + destX+" "+destY + } else { + + var midX = Math.floor(destX-dx/2); + var midY = Math.floor(destY-dy/2); + // + if (dx === 0) { + midX = destX + node_width; + } + var cp_width = node_width/2; + var x1 = (destX + midX)/2; + var topX = dx>0? Math.min(x1 - dx/2 , origX+cp_width) : Math.max(x1 - dx/2 , origX-cp_width); + var topY = origY + sc*node_height*scale; + var bottomX = dx>0?Math.max(x1, destX-cp_width):Math.min(x1, destX+cp_width); + var bottomY = destY - sc*node_height*scale; + var y1 = (origY+topY)/2; + var scx = dx>0?1:-1; + var cp = [ + [origX,y1], + [dx>0 ? Math.max(origX, topX-cp_width) : Math.min(origX, topX+cp_width), topY], + [dx>0 ? Math.max(midX, topX-cp_width) : Math.min(midX, topX-cp_width), y1], + [dx>0 ? Math.max(midX, bottomX-cp_width): Math.min(midX, bottomX+cp_width), bottomY], + [destX,(destY+bottomY)/2] + ]; + if (cp[2][0] === topX+scx*cp_width) { + if (Math.abs(dx) < cp_width*10) { + cp[1][0] = topX-scx*cp_width/2; + cp[3][0] = bottomX-scx*cp_width/2; + } + cp[2][1] = topY; + } + return "M "+origX+" "+origY+ + " C "+ + cp[0][0]+" "+cp[0][1]+" "+ + cp[1][0]+" "+cp[1][1]+" "+ + topX+" "+topY+ + " S "+ + cp[2][0]+" "+cp[2][1]+" "+ + midX+" "+midY+ + " S "+ + cp[3][0]+" "+cp[3][1]+" "+ + bottomX+" "+bottomY+ + " S "+ + cp[4][0]+" "+cp[4][1]+" "+ + destX+" "+destY + } + } + + function addNode(type,x,y) { var m = /^subflow:(.+)$/.exec(type); @@ -644,8 +715,13 @@ RED.view = (function() { nn.changed = true; nn.moved = true; - nn.w = node_width; - nn.h = Math.max(node_height,(nn.outputs||0) * 15); + if (vertical) { + nn.w = Math.max(node_width,(nn.outputs||0) * 15); + nn.h = node_height; + }else{ + nn.w = node_width; + nn.h = Math.max(node_height,(nn.outputs||0) * 15); + } nn.resize = true; var historyEvent = { @@ -786,9 +862,18 @@ RED.view = (function() { } var numOutputs = (quickAddLink.portType === PORT_TYPE_OUTPUT)?(quickAddLink.node.outputs || 1):1; var sourcePort = quickAddLink.port; - var portY = -((numOutputs-1)/2)*13 +13*sourcePort; + + if (vertical) { + var portX = -((numOutputs-1)/2)*13 +13*sourcePort; + }else{ + 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 (vertical) { + quickAddLink.el.attr("d",generateLinkPathV(quickAddLink.node.x+portX,quickAddLink.node.y+sc*quickAddLink.node.h/2,point[0]-sc*node_width/2,point[1],sc)); + }else{ + 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(); @@ -1142,10 +1227,18 @@ RED.view = (function() { var drag_line = drag_lines[i]; var numOutputs = (drag_line.portType === PORT_TYPE_OUTPUT)?(drag_line.node.outputs || 1):1; var sourcePort = drag_line.port; - var portY = -((numOutputs-1)/2)*13 +13*sourcePort; + if (vertical) { + var portX = -((numOutputs-1)/2)*13 +13*sourcePort; + }else{ + 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)); + if (vertical) { + drag_line.el.attr("d",generateLinkPathV(drag_line.node.x+portX,drag_line.node.y+sc*drag_line.node.h/2,mousePos[0],mousePos[1],sc)); + }else{ + 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(); } else if (mouse_mode == RED.state.MOVING) { @@ -2563,8 +2656,8 @@ RED.view = (function() { } nodeMouseUp.call(this,d); }); - - outGroup.append("g").attr('transform','translate(-5,15)').append("rect").attr("class","red-ui-flow-port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) + var attr_output_translate = (vertical) ? 'translate(15,-5)' : 'translate(-5,15)'; + outGroup.append("g").attr('transform',attr_output_translate).append("rect").attr("class","red-ui-flow-port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) .on("mousedown", function(d,i){portMouseDown(d,PORT_TYPE_INPUT,0);} ) .on("touchstart", function(d,i){portMouseDown(d,PORT_TYPE_INPUT,0);} ) .on("mouseup", function(d,i){portMouseUp(d,PORT_TYPE_INPUT,0);}) @@ -2606,8 +2699,8 @@ RED.view = (function() { } nodeMouseUp.call(this,d); }); - - inGroup.append("g").attr('transform','translate(35,15)').append("rect").attr("class","red-ui-flow-port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) + var attr_input_translate = (vertical) ? 'translate(15,35)' : 'translate(35,15)'; + inGroup.append("g").attr('transform',attr_input_translate).append("rect").attr("class","red-ui-flow-port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) .on("mousedown", function(d,i){portMouseDown(d,PORT_TYPE_OUTPUT,i);} ) .on("touchstart", function(d,i){portMouseDown(d,PORT_TYPE_OUTPUT,i);} ) .on("mouseup", function(d,i){portMouseUp(d,PORT_TYPE_OUTPUT,i);}) @@ -2649,8 +2742,8 @@ RED.view = (function() { } nodeMouseUp.call(this,d); }); - - statusGroup.append("g").attr('transform','translate(-5,15)').append("rect").attr("class","red-ui-flow-port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) + var attr_status_translate = (vertical) ? 'translate(15,-5)' : 'translate(-5,15)'; + statusGroup.append("g").attr('transform', attr_status_translate).append("rect").attr("class","red-ui-flow-port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) .on("mousedown", function(d,i){portMouseDown(d,PORT_TYPE_INPUT,0);} ) .on("touchstart", function(d,i){portMouseDown(d,PORT_TYPE_INPUT,0);} ) .on("mouseup", function(d,i){portMouseUp(d,PORT_TYPE_INPUT,0);}) @@ -2710,14 +2803,23 @@ RED.view = (function() { var hideLabel = d.hasOwnProperty('l')?!d.l : isLink; node.attr("id",d.id); var l = RED.utils.getNodeLabel(d); + if (d.resize || d.w === undefined) { if (hideLabel) { d.w = node_height; } else { - d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)) ); + if (vertical) { + d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)),(d.outputs||0) * 15 ); + }else{ + d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)) ); + } } } - d.h = Math.max(node_height,(d.outputs||0) * 15); + if (vertical) { + d.h = node_height; + }else{ + d.h = Math.max(node_height,(d.outputs||0) * 15); + } // if (d._def.badge) { // var badge = node.append("svg:g").attr("class","node_badge_group"); @@ -2960,13 +3062,21 @@ RED.view = (function() { if (d.resize) { var l = RED.utils.getNodeLabel(d); var ow = d.w; - if (hideLabel) { - d.w = node_height; - } else { - d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)) ); + if (vertical) { + if (hideLabel) { + d.w = node_height + } else { + d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)),(d.outputs||0) * 15 ); + } + d.h = node_height; + }else{ + if (hideLabel) { + d.w = node_height; + } else { + d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)) ); + } + d.h = Math.max(node_height,(d.outputs||0) * 15); } - // d.w = Math.max(node_width,20*(Math.ceil((calculateTextWidth(l, "red-ui-flow-node-label", 50)+(d._def.inputs>0?7:0))/20)) ); - d.h = Math.max(node_height,(d.outputs||0) * 15); d.x += (d.w-ow)/2; d.resize = false; } @@ -3007,7 +3117,7 @@ RED.view = (function() { if (d.type === "link in") { inputGroupPorts = inputGroup.append("circle") - .attr("cx",-1).attr("cy",5) + .attr("cx",vertical ? 5 : -1).attr("cy",vertical ? -1 : 5) .attr("r",5) .attr("class","red-ui-flow-port red-ui-flow-link-port") } else { @@ -3031,7 +3141,11 @@ RED.view = (function() { numOutputs = 0; } } - var y = (d.h/2)-((numOutputs-1)/2)*13; + if (vertical) { + var x = (d.w/2)-((numOutputs-1)/2)*13; + }else{ + var y = (d.h/2)-((numOutputs-1)/2)*13; + } d.ports = d.ports || d3.range(numOutputs); d._ports = thisNode.selectAll(".red-ui-flow-port-output").data(d.ports); var output_group = d._ports.enter().append("g").attr("class","red-ui-flow-port-output"); @@ -3039,7 +3153,7 @@ RED.view = (function() { if (d.type === "link out") { output_group_ports = output_group.append("circle") - .attr("cx",11).attr("cy",5) + .attr("cx",vertical ? 6 : 11).attr("cy", vertical ? 11 : 6) .attr("r",5) .attr("class","red-ui-flow-port red-ui-flow-link-port") } else { @@ -3060,11 +3174,21 @@ RED.view = (function() { d._ports.exit().remove(); if (d._ports) { numOutputs = d.outputs || 1; - y = (d.h/2)-((numOutputs-1)/2)*13; - var x = d.w - 5; + if (vertical) { + x = (d.w/2)-((numOutputs-1)/2)*13; + var y = d.h - 5; + }else{ + y = (d.h/2)-((numOutputs-1)/2)*13; + var x = d.w - 5; + } d._ports.each(function(d,i) { var port = d3.select(this); - port.attr("transform", function(d) { return "translate("+x+","+((y+13*i)-5)+")";}); + //port.attr("y",(y+13*i)-5).attr("x",x); + if (vertical) { + port.attr("transform", function(d) { return "translate("+((x+13*i)-5)+","+ y +")";}); + }else{ + port.attr("transform", function(d) { return "translate("+x+","+((y+13*i)-5)+")";}); + } }); } thisNode.selectAll("text.red-ui-flow-node-label").text(function(d,i){ @@ -3117,17 +3241,32 @@ RED.view = (function() { } } - thisNode.selectAll(".red-ui-flow-node-changed") - .attr("transform",function(d){return "translate("+(d.w-10)+", -2)"}) - .classed("hide",function(d) { return !(d.changed||d.moved); }); + if (vertical) { + thisNode.selectAll(".red-ui-flow-node-changed") + .attr("transform",function(d){return "translate("+(d.w-2)+", -2)"}) + .classed("hide",function(d) { return !(d.changed||d.moved); }); + + thisNode.selectAll(".red-ui-flow-node-error") + .attr("transform",function(d){ return "translate("+(d.w-2-((d.changed||d.moved)?14:0))+", -2)"}) + .classed("hide",function(d) { return d.valid; }); + } else { + thisNode.selectAll(".red-ui-flow-node-changed") + .attr("transform",function(d){return "translate("+(d.w-10)+", -2)"}) + .classed("hide",function(d) { return !(d.changed||d.moved); }); + + thisNode.selectAll(".red-ui-flow-node-error") + .attr("transform",function(d){ return "translate("+(d.w-10-((d.changed||d.moved)?14:0))+", -2)"}) + .classed("hide",function(d) { return d.valid; }); + } - thisNode.selectAll(".red-ui-flow-node-error") - .attr("transform",function(d){ return "translate("+(d.w-10-((d.changed||d.moved)?14:0))+", -2)"}) - .classed("hide",function(d) { return d.valid; }); thisNode.selectAll(".red-ui-flow-port-input").each(function(d,i) { - var port = d3.select(this); - port.attr("transform",function(d){return "translate(-5,"+((d.h/2)-5)+")";}) + var port = d3.select(this); + if (vertical) { + port.attr("transform",function(d){return "translate("+((d.w/2)-5)+", -5)";}) + }else{ + port.attr("transform",function(d){return "translate(-5,"+((d.h/2)-5)+")";}) + } }); thisNode.selectAll(".red-ui-flow-node-icon").attr("y",function(d){return (d.h-d3.select(this).attr("height"))/2;}); @@ -3192,9 +3331,17 @@ RED.view = (function() { var fill = status_colours[d.status.fill]; // Only allow our colours for now if (d.status.shape == null && fill == null) { thisNode.selectAll(".red-ui-flow-node-status").style("display","none"); - thisNode.selectAll(".red-ui-flow-node-status-group").attr("transform","translate(-14,"+(d.h+3)+")"); + if (vertical) { + thisNode.selectAll(".red-ui-flow-node-status-group").attr("transform","translate(" + (-14+d.w/2) + ","+(d.h+3)+")"); + } else { + thisNode.selectAll(".red-ui-flow-node-status-group").attr("transform","translate(-14,"+(d.h+3)+")"); + } } else { - thisNode.selectAll(".red-ui-flow-node-status-group").attr("transform","translate(3,"+(d.h+3)+")"); + if (vertical) { + thisNode.selectAll(".red-ui-flow-node-status-group").attr("transform","translate(" + (3 + d.w/2) + ","+(d.h+3)+")"); + } else { + thisNode.selectAll(".red-ui-flow-node-status-group").attr("transform","translate(3,"+(d.h+3)+")"); + } var statusClass = "red-ui-flow-node-status-"+(d.status.shape||"dot")+"-"+d.status.fill; thisNode.selectAll(".red-ui-flow-node-status").style("display","inline").attr("class","red-ui-flow-node-status "+statusClass); } @@ -3279,17 +3426,23 @@ RED.view = (function() { link.attr("d",function(d){ var numOutputs = d.source.outputs || 1; var sourcePort = d.sourcePort || 0; - var y = -((numOutputs-1)/2)*13 +13*sourcePort; - d.x1 = d.source.x+d.source.w/2; - d.y1 = d.source.y+y; - d.x2 = d.target.x-d.target.w/2; - d.y2 = d.target.y; + var path; + if (vertical) { + var x = -((numOutputs-1)/2)*13 +13*sourcePort; + d.x1 = d.source.x+x; + d.y1 = d.source.y+d.source.h/2; + d.x2 = d.target.x; + d.y2 = d.target.y-d.target.h/2; + path = generateLinkPathV(d.x1,d.y1,d.x2,d.y2,1); + }else{ + var y = -((numOutputs-1)/2)*13 +13*sourcePort; + d.x1 = d.source.x+d.source.w/2; + d.y1 = d.source.y+y; + d.x2 = d.target.x-d.target.w/2; + d.y2 = d.target.y; + path = generateLinkPath(d.x1,d.y1,d.x2,d.y2,1); + } - // return "M "+d.x1+" "+d.y1+ - // " C "+(d.x1+scale*node_width)+" "+(d.y1+scaleY*node_height)+" "+ - // (d.x2-scale*node_width)+" "+(d.y2-scaleY*node_height)+" "+ - // d.x2+" "+d.y2; - var path = generateLinkPath(d.x1,d.y1,d.x2,d.y2,1); if (/NaN/.test(path)) { return "" } @@ -3780,6 +3933,14 @@ RED.view = (function() { updateGrid(); } }, + vertical: function(v) { + if (v === undefined) { + return vertical; + } else { + vertical = v; + RED.view.redraw(); + } + }, getActiveNodes: function() { return activeNodes; },