288 lines
8.6 KiB
TypeScript
288 lines
8.6 KiB
TypeScript
|
/**
|
||
|
* @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,
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|