nope/resources/ui/gojs/nodes/helpers.ts

288 lines
8.6 KiB
TypeScript
Raw Normal View History

2021-08-04 16:17:23 +00:00
/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2021-07-30 07:53:50
* @modify date 2021-07-30 07:53:50
* @desc [description]
*/
import go from "gojs";
// Create the Make function for
const make = go.GraphObject.make; // for conciseness in defining templates
// some constants that will be reused within templates
const mtb8 = new go.Margin(8, 0, 8, 0);
const mr8 = new go.Margin(0, 8, 0, 0);
const ml8 = new go.Margin(0, 0, 0, 8);
const mrl8 = new go.Margin(0, 8, 0, 8);
/**
* Creates a Textblock
* This textblock is only visible, if data in the "field" is available.
* @param field {string}: Name of the Field, where the text ist integratec
* @returns go.TextBlock
*/
export function textStyle(field: string): go.TextBlock {
return make(
go.TextBlock,
{
font: "12px Roboto, sans-serif",
stroke: "rgba(0, 0, 0, .60)",
visible: false // only show textblocks when there is corresponding data for them
},
new go.Binding("visible", field, function (val) {
return val !== undefined;
}),
{
row: 1,
alignment: go.Spot.Left,
editable: true,
isMultiline: true
},
new go.Binding("text", field)
);
}
/**
* Function to create visible Divider.
* @param {string} visibleTag if provided this flag, determines wheter the Bar is rendered or not.
* @returns {go.Shape} the Bar
*/
export function horizontalDivider(visibleTag: string = null): go.Shape {
// Create an additional Tag, that will be used to toggle the bar
// if desired.
const additional = [];
if (visibleTag !== null) {
additional.push(new go.Binding("visible", "showDetails"));
}
return make(
go.Shape,
"LineH",
{
stroke: "rgba(0, 0, 0, .60)",
strokeWidth: 1,
height: 1,
stretch: go.GraphObject.Horizontal
},
...additional
);
}
/**
* Generates a Helper function, that will be used to define a Port.
* @param directedPortDirections
* @returns Function
*/
export function generatePortMaker(options: {
directedPortDirections?: boolean,
} = {}): (name: string, align: go.Spot, spot: go.Spot, output: boolean, input: boolean) => go.Shape {
/**
* Define a function for creating a "port" that is normally transparent.
* The "name" is used as the GraphObject.portId,
* the "align" is used to determine where to position the port relative to the body of the node,
* the "spot" is used to control how links connect with the port and whether the port
* stretches along the side of the node,
* and the boolean "output" and "input" arguments control whether the user can draw links from or to the port.
* @param name Name of th Port
* @param align Orientation to Align
* @param spot The Spot to render
* @param output Flag, to show that this is an output or not
* @param input Flag, to show that this is an input or not
* @returns
*/
function makePort(name: string, align: go.Spot, spot: go.Spot, output: boolean, input: boolean): go.Shape {
// Create an additional Tag, that will be used to toggle the bar
// if desired.
const additional = [];
if (options.directedPortDirections !== false) {
additional.push(
output ? {
fromSpot: spot, // declare where links may connect at this port
} : {}, input ? {
toSpot: spot, // declare where links may connect at this port
} : {}
);
}
const horizontal =
align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
// the port is basically just a transparent rectangle that stretches along the side of the node,
// and becomes colored when the mouse passes over it
return make(go.Shape, Object.assign({
fill: "transparent", // changed to a color in the mouseEnter event handler
strokeWidth: 0, // no stroke
width: horizontal ? NaN : 8, // if not stretching horizontally, just 8 wide
height: !horizontal ? NaN : 8, // if not stretching vertically, just 8 tall
alignment: align, // align the port on the main Shape
stretch: horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical,
portId: name, // declare this object to be a "port"
// fromSpot: spot, // declare where links may connect at this port
fromLinkable: output, // declare whether the user may draw links from here
// toSpot: spot, // declare where links may connect at this port
toLinkable: input, // declare whether the user may draw links to here
cursor: "pointer", // show a different cursor to indicate potential link point
mouseEnter: function (e, port) {
// the PORT argument will be this Shape
if (!e.diagram.isReadOnly) {
port.fill = "rgba(255,0,255,0.5)";
e.diagram.linkTemplate = e.diagram.linkTemplateMap.get("logicFlow");
e.diagram.toolManager.linkingTool.archetypeLinkData = {
category: "logicFlow"
};
}
},
mouseLeave: function (e, port) {
port.fill = "transparent";
}
},
...additional
)
);
}
return makePort;
}
/**
* @param {{additionalParameters?:anyinputName?:string} options
* @param {stringpart:go.PartvisibleTag?:string}} outputName?
* @returns go
*/
export function createSegementGenerator(options: {
inputName?: string,
outputName?: string
part: go.Part
visibleTag?: string
}): go.Panel {
// Create a Vertical Panel.
function makeVerticalPanel(
binding: string,
side: "left" | "right",
portSize = new go.Size(8, 8)
) {
let order: any = [];
if (side === "left") {
order = [
make(
go.Shape,
"RoundedRectangle",
{
stroke: null,
strokeWidth: 0,
desiredSize: portSize,
margin: new go.Margin(1, 0)
},
new go.Binding("fill", "portColor")
),
make(
go.TextBlock,
{
row: 0,
alignment: go.Spot.Left,
font: "16px Roboto, sans-serif",
stroke: "rgba(0, 0, 0, .87)",
margin: mrl8
},
new go.Binding("text", "label")
)
];
} else {
order = [
make(
go.TextBlock,
{
row: 0,
alignment: go.Spot.Left,
font: "16px Roboto, sans-serif",
stroke: "rgba(0, 0, 0, .87)",
maxSize: new go.Size(160, NaN),
margin: mrl8
},
new go.Binding("text", "label")
),
make(
go.Shape,
"RoundedRectangle",
{
stroke: null,
strokeWidth: 0,
desiredSize: portSize,
margin: new go.Margin(1, 0)
},
new go.Binding("fill", "portColor")
)
];
}
return make(go.Panel, "Vertical", new go.Binding("itemArray", binding), {
alignment: side === "left" ? go.Spot.Left : go.Spot.Right,
itemTemplate: make(
go.Panel,
"Horizontal",
Object.assign({
_side: side, // internal property to make it easier to tell which side it's on
fromLinkable: side !== "left",
toLinkable: side === "left",
cursor: "pointer",
alignment: side === "left" ? go.Spot.Left : go.Spot.Right,
mouseEnter: function (e, port) {
// the PORT argument will be this Shape
if (!e.diagram.isReadOnly) {
port.fill = "rgba(255,0,255,0.5)";
e.diagram.linkTemplate = e.diagram.linkTemplateMap.get("dataFlow");
e.diagram.toolManager.linkingTool.archetypeLinkData = {
category: "dataFlow"
};
}
},
}, side !== "left" ? { fromSpot: go.Spot.RightSide } : { toSpot: go.Spot.Left })
,
new go.Binding("portId", "portId"),
...order
) // end itemTemplate
}); // end Vertical Panel
}
// Create an additional Tag, that will be used to toggle the bar
// if desired.
const additional = [];
if (options.inputName !== undefined) {
additional.push(makeVerticalPanel(options.inputName, "left"));
}
// Add the Middle Section
if (options.part !== undefined) {
additional.push(options.part);
}
// Add the Output-Section if desired
if (options.outputName !== undefined) {
additional.push(makeVerticalPanel(options.outputName, "right"));
}
// Add the binding to toggle the Bind
if (typeof options.visibleTag === "string") {
additional.push(new go.Binding("visible", options.visibleTag));
}
return make(
go.Panel,
"Auto",
{
margin: mtb8,
stretch: go.GraphObject.Fill,
},
...additional,
);
}