1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

[groups] Add style options for group label

This commit is contained in:
Nick O'Leary 2020-03-20 20:00:03 +00:00
parent 58696c6ad4
commit 20a8059758
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
5 changed files with 461 additions and 17 deletions

View File

@ -15,7 +15,7 @@
"next": "Next",
"clone": "Clone project",
"cont": "Continue",
"stroke": "Stroke",
"line": "Outline",
"fill": "Fill"
},
"type": {

View File

@ -0,0 +1,223 @@
RED.colorPicker = (function() {
function getDarkerColor(c) {
var r,g,b;
if (/^#[a-f0-9]{6}$/i.test(c)) {
r = parseInt(c.substring(1, 3), 16);
g = parseInt(c.substring(3, 5), 16);
b = parseInt(c.substring(5, 7), 16);
} else if (/^#[a-f0-9]{3}$/i.test(c)) {
r = parseInt(c.substring(1, 2)+c.substring(1, 2), 16);
g = parseInt(c.substring(2, 3)+c.substring(2, 3), 16);
b = parseInt(c.substring(3, 4)+c.substring(3, 4), 16);
} else {
return c;
}
var l = 0.3 * r/255 + 0.59 * g/255 + 0.11 * b/255 ;
r = Math.max(0,r-50);
g = Math.max(0,g-50);
b = Math.max(0,b-50);
return '#'+((r<<16) + (g<<8) + b).toString(16).padStart(6,'0')
}
function create(options) {
var color = options.value;
var id = options.id;
var colorPalette = options.palette || [];
var width = options.cellWidth || 30;
var height = options.cellHeight || 30;
var margin = options.cellMargin || 2;
var perRow = options.cellPerRow || 6;
var container = $("<div>",{style:"display:inline-block"});
var colorHiddenInput = $("<input/>", { id: id, type: "hidden", value: color }).appendTo(container);
var opacityHiddenInput = $("<input/>", { id: id+"-opacity", type: "hidden", value: options.hasOwnProperty('opacity')?options.opacity:"1" }).appendTo(container);
var colorButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(container);
$('<i class="fa fa-caret-down"></i>').appendTo(colorButton);
var colorDispContainer = $('<div>',{class:"red-ui-search-result-node"}).appendTo(colorButton);
$('<div>',{class:"red-ui-color-picker-cell-none"}).appendTo(colorDispContainer);
var colorDisp = $('<div>',{class:"red-ui-color-picker-swatch"}).appendTo(colorDispContainer);
var refreshDisplay = function(color) {
if (color === "none") {
colorDisp.addClass('red-ui-color-picker-cell-none').css({
"background-color": "",
opacity: 1
});
colorDispContainer.css({
"border-color":""
})
} else {
var opacity = parseFloat(opacityHiddenInput.val())
colorDisp.removeClass('red-ui-color-picker-cell-none').css({
"background-color": color,
"opacity": opacity
});
var border = getDarkerColor(color);
if (border[0] === '#') {
border += Math.round(255*Math.floor(opacity*100)/100).toString(16);
} else {
border = "";
}
colorDispContainer.css({
"border-color": border
})
}
if (options.hasOwnProperty('opacity')) {
$(".red-ui-color-picker-opacity-slider-overlay").css({
"background-image": "linear-gradient(90deg, transparent 0%, "+color+" 100%)"
})
}
}
colorButton.on("click", function (e) {
var numColors = colorPalette.length;
var picker = $("<div/>", {
class: "red-ui-color-picker"
}).css({
width: ((width+margin+margin)*perRow)+"px",
height: Math.ceil(numColors/perRow)*(height+margin+margin)+"+px"
});
var count = 0;
var row = null;
row = $("<div/>").appendTo(picker);
var colorInput = $('<input>',{
type:"text",
value:colorHiddenInput.val()
}).appendTo(row);
colorInput.on("change", function (e) {
var color = colorInput.val();
colorHiddenInput.val(color).trigger('change');
refreshDisplay(color);
});
// if (options.hasOwnProperty('opacity')) {
// var sliderContainer = $("<div>",{class:"red-ui-color-picker-opacity-slider"
// }
if (options.none) {
row = $("<div/>").appendTo(picker);
var button = $("<button/>", {
class:"red-ui-color-picker-cell red-ui-color-picker-cell-none"
}).css({
width: width+"px",
height: height+"px",
margin: margin+"px"
}).appendTo(row);
button.on("click", function (e) {
e.preventDefault();
colorInput.val("none");
colorInput.trigger("change");
});
}
colorPalette.forEach(function (col) {
if ((count % perRow) == 0) {
row = $("<div/>").appendTo(picker);
}
var button = $("<button/>", {
class:"red-ui-color-picker-cell"
}).css({
width: width+"px",
height: height+"px",
margin: margin+"px",
backgroundColor: col,
"border-color": getDarkerColor(col)
}).appendTo(row);
button.on("click", function (e) {
e.preventDefault();
// colorPanel.hide();
colorInput.val(col);
colorInput.trigger("change");
});
count++;
});
if (options.none || options.hasOwnProperty('opacity')) {
row = $("<div/>").appendTo(picker);
// if (options.none) {
// var button = $("<button/>", {
// class:"red-ui-color-picker-cell red-ui-color-picker-cell-none"
// }).css({
// width: width+"px",
// height: height+"px",
// margin: margin+"px"
// }).appendTo(row);
// button.on("click", function (e) {
// e.preventDefault();
// colorPanel.hide();
// selector.val("none");
// selector.trigger("change");
// });
// }
if (options.hasOwnProperty('opacity')) {
var sliderContainer = $("<div>",{class:"red-ui-color-picker-opacity-slider"}).appendTo(row);
sliderContainer.on("mousedown", function(evt) {
if (evt.target === sliderHandle[0]) {
return;
}
var v = evt.offsetX/sliderContainer.width();
sliderHandle.css({
left: ( v*(sliderContainer.width() - sliderHandle.outerWidth()))+"px"
});
v = Math.floor(100*v)
opacityHiddenInput.val(v/100)
opacityLabel.text(v+"%");
refreshDisplay(colorHiddenInput.val());
})
$("<div>",{class:"red-ui-color-picker-opacity-slider-overlay"}).appendTo(sliderContainer);
var sliderHandle = $("<div>",{class:"red-ui-color-picker-opacity-slider-handle red-ui-button red-ui-button-small"}).appendTo(sliderContainer).draggable({
containment: "parent",
axis: "x",
drag: function( event, ui ) {
var v = Math.max(0,ui.position.left/($(this).parent().width()-$(this).outerWidth()));
// Odd bug that if it is loaded with a non-0 value, the first time
// it is dragged it ranges -1 to 99. But every other time, its 0 to 100.
// The Math.max above makes the -1 disappear. The follow hack ensures
// it always maxes out at a 100, at the cost of not allowing 99% exactly.
v = Math.floor(100*v)
if ( v === 99 ) {
v = 100;
}
// console.log("uip",ui.position.left);
opacityHiddenInput.val(v/100)
opacityLabel.text(v+"%");
refreshDisplay(colorHiddenInput.val());
}
});
var opacityLabel = $('<small></small>').appendTo(row);
setTimeout(function() {
sliderHandle.css({
left: (parseFloat(opacityHiddenInput.val())*(sliderContainer.width() - sliderHandle.outerWidth()))+"px"
})
opacityLabel.text(Math.floor(opacityHiddenInput.val()*100)+"%");
},50);
}
}
var colorPanel = RED.popover.panel(picker);
setTimeout(function() {
refreshDisplay(colorHiddenInput.val())
},50);
colorPanel.show({
target: colorButton
})
});
setTimeout(function() {
refreshDisplay(colorHiddenInput.val())
},50);
return container;
}
return {
create: create
}
})();

View File

@ -22,12 +22,41 @@ RED.group = (function() {
'<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">'+
'</div>'+
// '<div class="form-row">'+
// '<label>Style</label>'+
// '<span style="display: inline-block; min-width: 140px" id="node-input-row-style-stroke">'+
// '<label style="width: 70px;margin-right: 10px " for="node-input-style-stroke" data-i18n="editor:common.label.line"></label>'+
// '</span>'+
// '<span style="display: inline-block; min-width: 140px; margin-left: 10px" id="node-input-row-style-fill">'+
// '<label style="width: 70px;margin-right: 10px " for="node-input-style-fill" data-i18n="editor:common.label.fill"></label>'+
// '</span>'+
// '</div>'+
'<div class="form-row" id="node-input-row-style-stroke">'+
'<label for="node-input-style-stroke" data-i18n="editor:common.label.stroke"></label>'+
'<label>Style</label>'+
'<label style="width: 70px;margin-right:10px" for="node-input-style-stroke" data-i18n="editor:common.label.line"></label>'+
'</div>'+
'<div class="form-row" style="padding-left: 100px;" id="node-input-row-style-fill">'+
'<label style="width: 70px;margin-right: 10px " for="node-input-style-fill" data-i18n="editor:common.label.fill"></label>'+
'</div>'+
'<div class="form-row" id="node-input-row-style-fill">'+
'<label for="node-input-style-fill" data-i18n="editor:common.label.fill"></label>'+
'<div class="form-row">'+
'<label for="node-input-style-label">Label</label>'+
'<input type="checkbox" id="node-input-style-label"/>'+
'</div>'+
'<div class="form-row" id="node-input-row-style-label-options">'+
'<div style="margin-left: 100px; display: inline-block">'+
'<div class="form-row">'+
'<span style="display: inline-block; min-width: 140px" id="node-input-row-style-label-color">'+
'<label style="width: 70px;margin-right: 10px" for="node-input-style-fill">Color</label>'+
'</span>'+
'</div>'+
'<div class="form-row">'+
'<span style="display: inline-block; min-width: 140px;" id="node-input-row-style-label-position">'+
'<label style="width: 70px;margin-right: 10px " for="node-input-style-label-position">Position</label>'+
'</span>'+
'</div>'+
'</div>'+
'</div>'+
'</script>';
@ -73,7 +102,7 @@ RED.group = (function() {
var style = this.style || {};
RED.colorPicker.create({
id:"node-input-style-stroke",
value: style.stroke || "#c0c0c0",
value: style.stroke || "#a4a4a4",
palette: colorPalette,
cellPerRow: colorCount,
cellWidth: 16,
@ -84,7 +113,7 @@ RED.group = (function() {
}).appendTo("#node-input-row-style-stroke");
RED.colorPicker.create({
id:"node-input-style-fill",
value: style.fill || "#c0c0c0",
value: style.fill || "none",
palette: colorPalette,
cellPerRow: colorCount,
cellWidth: 16,
@ -93,6 +122,34 @@ RED.group = (function() {
none: true,
opacity: style['fill-opacity'] || 1.0
}).appendTo("#node-input-row-style-fill");
createLayoutPicker({
id:"node-input-style-label-position",
value:style["label-position"] || "nw"
}).appendTo("#node-input-row-style-label-position");
RED.colorPicker.create({
id:"node-input-style-color",
value: style.color || "#a4a4a4",
palette: colorPalette,
cellPerRow: colorCount,
cellWidth: 16,
cellHeight: 16,
cellMargin: 3
}).appendTo("#node-input-row-style-label-color");
$("#node-input-style-label").toggleButton({
enabledLabel: RED._("editor.show"),
disabledLabel: RED._("editor.hide")
})
$("#node-input-style-label").on("change", function(evt) {
$("#node-input-row-style-label-options").toggle($(this).prop("checked"));
})
$("#node-input-style-label").prop("checked", this.style.label)
$("#node-input-style-label").trigger("change");
},
oneditresize: function(size) {
},
@ -101,7 +158,21 @@ RED.group = (function() {
this.style.fill = $("#node-input-style-fill").val();
this.style["stroke-opacity"] = $("#node-input-style-stroke-opacity").val();
this.style["fill-opacity"] = $("#node-input-style-fill-opacity").val();
this.style.label = $("#node-input-style-label").prop("checked");
if (this.style.label) {
this.style["label-position"] = $("#node-input-style-label-position").val();
this.style.color = $("#node-input-style-color").val();
} else {
delete this.style["label-position"];
delete this.style.color;
}
if (this.style["stroke-opacity"] === "1") {
delete this.style["stroke-opacity"]
}
if (this.style["fill-opacity"] === "1") {
delete this.style["fill-opacity"]
}
},
set:{
module: "node-red"
@ -421,6 +492,64 @@ RED.group = (function() {
return getRootGroup(RED.nodes.group(group.g))
}
function createLayoutPicker(options) {
var container = $("<div>",{style:"display:inline-block"});
var layoutHiddenInput = $("<input/>", { id: options.id, type: "hidden", value: options.value }).appendTo(container);
var layoutButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(container);
$('<i class="fa fa-caret-down"></i>').appendTo(layoutButton);
var layoutDispContainer = $('<div>',{class:"red-ui-search-result-node"}).appendTo(layoutButton);
var layoutDisp = $('<div>',{class:"red-ui-group-layout-picker-cell-text red-ui-group-layout-text-pos-"}).appendTo(layoutDispContainer);
var refreshDisplay = function() {
var val = layoutHiddenInput.val();
layoutDisp.removeClass().addClass("red-ui-group-layout-picker-cell-text red-ui-group-layout-text-pos-"+val)
}
layoutButton.on("click", function(e) {
var picker = $("<div/>", {
class: "red-ui-group-layout-picker"
}).css({
width: "126px"
});
var row = null;
row = $("<div/>").appendTo(picker);
for (var y=0;y<2;y++) { //red-ui-group-layout-text-pos
var yComponent= "ns"[y];
row = $("<div/>").appendTo(picker);
for (var x=0;x<3;x++) {
var xComponent = ["w","","e"][x];
var val = yComponent+xComponent;
var button = $("<button/>", { class:"red-ui-search-result-node","data-pos":val }).appendTo(row);
button.on("click", function (e) {
e.preventDefault();
layoutHiddenInput.val($(this).data("pos"));
layoutPanel.hide()
refreshDisplay();
});
$('<div>',{class:"red-ui-group-layout-picker-cell-text red-ui-group-layout-text-pos-"+val}).appendTo(button);
}
}
refreshDisplay();
var layoutPanel = RED.popover.panel(picker);
layoutPanel.show({
target: layoutButton
})
})
refreshDisplay();
return container;
}
return {
def: groupDef,

View File

@ -2040,9 +2040,7 @@ if (DEBUG_EVENTS) { console.warn("clearSelection", mouse_mode); }
}
var groups = activeGroups.filter(function(g) { return g.selected && !g.active });
while (groups.length > 0) {
console.log("GROUPS",groups.slice())
var group = groups.shift();
console.log("GROUP",group);
nodes.push(group);
groups = groups.concat(group.nodes.filter(function(n) { return n.type === "group" }))
}
@ -2070,7 +2068,6 @@ if (DEBUG_EVENTS) { console.warn("clearSelection", mouse_mode); }
}
}
clipboard = JSON.stringify(nns);
console.warn(nns);
RED.notify(RED._("clipboard.nodeCopied",{count:nns.length}),{id:"clipboard"});
}
}
@ -4102,6 +4099,17 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); }
"stroke-opacity": 0,
"stroke-width": 12
})
g.append('rect').classed("red-ui-flow-group-outline-select",true)
.attr('rx',0.5).attr('ry',0.5)
.attr("x",-4)
.attr("y",-4)
.style({
"fill":"none",
"stroke": "#ff7f0e",
"pointer-events": "stroke",
"stroke-opacity": 0,
"stroke-width": 4
})
g.append('rect').classed("red-ui-flow-group-body",true)
.attr('rx',1).attr('ry',1).style({
@ -4112,7 +4120,7 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); }
"stroke-width": 2
})
g.on("mousedown",groupMouseDown).on("mouseup",groupMouseUp)
g.append('svg:text').attr("class","red-ui-flow-group-label").text(d.name);
d.dirty = true;
});
@ -4148,16 +4156,50 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); }
g.selectAll(".red-ui-flow-group-outline")
.attr("width",d.w)
.attr("height",d.h)
.style("stroke-opacity",function(d) { if (d.selected) { return 0.8 } return 0});
// .style("stroke-opacity",d.selected?0.8:0);
g.selectAll(".red-ui-flow-group-outline-select")
.attr("width",d.w+8)
.attr("height",d.h+8)
.style("stroke-opacity",d.selected?0.8:0)
.style("stroke-dasharray", (d.active||d.hovered)?"10 4":"none")
g.selectAll(".red-ui-flow-group-body")
.attr("width",d.w)
.attr("height",d.h)
.style("stroke",function(d) { /*if (d.selected) { return "#ff7f0e" } */return d.style.stroke || "none"})
.style("stroke-opacity", function(d) { return d.style.hasOwnProperty('stroke-opacity') ? d.style['stroke-opacity'] : 1})
.style("stroke-dasharray", function(d) { return (d.active||d.hovered)?"10 4":"none"})
.style("fill", function(d) { return d.style.fill || "none"})
.style("fill-opacity", function(d) { return d.style.hasOwnProperty('fill-opacity') ? d.style['fill-opacity'] : 1})
.style("stroke", d.style.stroke || "none")
.style("stroke-opacity", d.style.hasOwnProperty('stroke-opacity') ? d.style['stroke-opacity'] : 1)
.style("fill", d.style.fill || "none")
.style("fill-opacity", d.style.hasOwnProperty('fill-opacity') ? d.style['fill-opacity'] : 1)
var label = g.selectAll(".red-ui-flow-group-label");
label.classed("hide",!!!d.style.label)
if (d.style.label) {
var labelPos = d.style["label-position"] || "nw";
var labelX = 0;
var labelY = 0;
if (labelPos[0] === 'n') {
labelY = 0+15; // Allow for font-height
} else {
labelY = d.h - 5;
}
if (labelPos[1] === 'w') {
labelX = 5;
labelAnchor = "start"
} else if (labelPos[1] === 'e') {
labelX = d.w-5;
labelAnchor = "end"
} else {
labelX = d.w/2;
labelAnchor = "middle"
}
label.text(d.name)
.style("fill", d.style.hasOwnProperty('color')?d.style.color:"#999")
.attr("transform","translate("+labelX+","+labelY+")")
.attr("text-anchor",labelAnchor);
}
// g.selectAll(".red-ui-flow-group-handle-0")
// .style("opacity",function(d) { return d.selected?1:0})

View File

@ -410,6 +410,51 @@ button.red-ui-button.red-ui-editor-node-appearance-button {
}
}
.red-ui-group-layout-picker {
padding: 5px;
background: $primary-background;
}
.red-ui-group-layout-picker-cell-text {
position: absolute;
width: 14px;
height: 2px;
border-top: 2px solid $secondary-text-color;
border-bottom: 2px solid $secondary-text-color;
margin: 2px;
&.red-ui-group-layout-text-pos-nw { top: 0; left: 0; }
&.red-ui-group-layout-text-pos-n { top: 0; left: calc(50% - 9px); }
&.red-ui-group-layout-text-pos-ne { top: 0; right: 0; }
&.red-ui-group-layout-text-pos-sw { bottom: 0; left: 0; }
&.red-ui-group-layout-text-pos-s { bottom: 0; left: calc(50% - 9px); }
&.red-ui-group-layout-text-pos-se { bottom: 0; right: 0; }
&.red-ui-group-layout-text-pos- {
width: 100%;
height: 100%;
border-radius: 5px;
margin: 0;
background-color: #FFF;
background-size: 100% 100%;
background-position: 0 0, 50% 50%;
background-image: linear-gradient(45deg, transparent 45%, $secondary-border-color 45%, $secondary-border-color 55%, transparent 55%, transparent),linear-gradient(-45deg, transparent 45%, $secondary-border-color 45%, $secondary-border-color 55%, transparent 55%, transparent);
border: none;
}
}
.red-ui-group-layout-picker button.red-ui-search-result-node {
float: none;
position: relative;
padding: 0;
margin: 5px;
width: 32px;
height: 27px;
}
button.red-ui-group-layout-picker-none {
width: 100%;
}
.red-ui-color-picker {
input[type="text"] {
border-radius:0;
@ -428,6 +473,11 @@ button.red-ui-button.red-ui-editor-node-appearance-button {
}
background: $primary-background;
}
.red-ui-editor-node-appearance-button {
.red-ui-search-result-node {
overflow: hidden
}
}
.red-ui-color-picker-cell {
padding: 0;
border-style: solid;
@ -436,7 +486,7 @@ button.red-ui-button.red-ui-editor-node-appearance-button {
}
.red-ui-color-picker-swatch {
position: absolute;
top:0;right:0;left:0;bottom:0;
top:-1px;right:-1px;left:-1px;bottom:-1px;
border-radius: 4px;
}