/** * @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, ); }