From 392aebe0df4eafcc2bbc6ca150d6a588d5858ab8 Mon Sep 17 00:00:00 2001 From: Gregory Bednov Date: Thu, 16 Jan 2025 06:19:32 +0300 Subject: [PATCH] first tries on adding MORE shapes to represent true gost fsa --- package-lock.json | 37 ++++ package.json | 1 + resources/hovered/icon-connect.svg | 5 + resources/icon-connect.svg | 5 + src/AddObjectForm.svelte | 285 ++++++++++++++++++++++++++ src/App.svelte | 2 + src/CustomGlobalConnectRules.ts | 43 ++++ src/CustomGlobalConnectRulesModule.ts | 8 + src/CustomOutlineModule.ts | 62 ++++++ src/CustomPaletteModule.ts | 21 +- src/CustomShapeRendererModule.ts | 71 +++++++ src/Diagram.svelte | 59 +----- src/ManhattanConnectionModule.ts | 37 ++-- src/editor.ts | 12 +- src/style.css | 8 + 15 files changed, 577 insertions(+), 79 deletions(-) create mode 100644 resources/hovered/icon-connect.svg create mode 100644 resources/icon-connect.svg create mode 100644 src/AddObjectForm.svelte create mode 100644 src/CustomGlobalConnectRules.ts create mode 100644 src/CustomGlobalConnectRulesModule.ts create mode 100644 src/CustomOutlineModule.ts create mode 100644 src/CustomShapeRendererModule.ts diff --git a/package-lock.json b/package-lock.json index 9b5a03d..7bbec46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "name": "diagram-js-svelte", "version": "0.0.0", "dependencies": { + "choices": "^0.1.3", + "choices.js": "^11.0.3", "diagram-js": "^15.2.4" }, "devDependencies": { @@ -884,6 +886,24 @@ "node": ">= 0.4" } }, + "node_modules/choices": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/choices/-/choices-0.1.3.tgz", + "integrity": "sha512-nRfQygGhPxh51vXoR6m7jUDqTb8UUmdqKCn6FfqFUJks4d+9ew8FDXJzDxVStZMh/Sn7rxKk5kXDwyOt3I5jfQ==", + "license": "BSD", + "dependencies": { + "colors": "^0.6.2" + } + }, + "node_modules/choices.js": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-11.0.3.tgz", + "integrity": "sha512-sn1oLUEcvjj7vSSIT0QyexmLIeD6PFGSWrUUXKShL2LUtVFXU3OAIY/smNIQg0OKav3yk1rFa+F56hZ/uYC4cg==", + "license": "MIT", + "dependencies": { + "fuse.js": "^7.0.0" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -893,6 +913,14 @@ "node": ">=6" } }, + "node_modules/colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/component-event": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/component-event/-/component-event-0.2.1.tgz", @@ -1040,6 +1068,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/fuse.js": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz", + "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, "node_modules/htm": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz", diff --git a/package.json b/package.json index c37b73d..a3ee3fa 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "vite": "^6.0.5" }, "dependencies": { + "choices.js": "^11.0.3", "diagram-js": "^15.2.4" } } diff --git a/resources/hovered/icon-connect.svg b/resources/hovered/icon-connect.svg new file mode 100644 index 0000000..e25c755 --- /dev/null +++ b/resources/hovered/icon-connect.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/resources/icon-connect.svg b/resources/icon-connect.svg new file mode 100644 index 0000000..a824ae0 --- /dev/null +++ b/resources/icon-connect.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/src/AddObjectForm.svelte b/src/AddObjectForm.svelte new file mode 100644 index 0000000..ec8ae08 --- /dev/null +++ b/src/AddObjectForm.svelte @@ -0,0 +1,285 @@ + + +
+ +
+ + {#if типОбъекта === 'Прибор'} + +
+ + +
+ + +
+ + +
+ + +
+ +Функции + {#each функции as функция, i} +
+ + + + +
+ {/each} + + + {:else} + +
+ + +
+ {/if} +
+ +
+
+ \ No newline at end of file diff --git a/src/App.svelte b/src/App.svelte index 37ed092..81c8ca4 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1,9 +1,11 @@

FSA Editor

+
diff --git a/src/CustomGlobalConnectRules.ts b/src/CustomGlobalConnectRules.ts new file mode 100644 index 0000000..210f8bd --- /dev/null +++ b/src/CustomGlobalConnectRules.ts @@ -0,0 +1,43 @@ +import RuleProvider from 'diagram-js/lib/features/rules/RuleProvider'; +export default class CustomGlobalConnectRules extends RuleProvider { + static $inject = ['eventBus']; + + constructor(eventBus: any) { + super(eventBus); + } + + init(): void { + // Правило для начала соединения + this.addRule('connection.start', (context) => { + return true; + const { source } = context; + + if (source?.businessObject?.type === 'custom:connectable') { + return true; // Разрешить соединение + } + + return false; // Запретить соединение + }); + + // Правило для создания соединения + this.addRule('connection.create', (context) => { + //return true; + const { source, target } = context; + // console.log(typeof source); + // console.log(source.constructor.name) + // instanceof Shape); + + //if (source?.type === Shape) + + //if ( + // source?.businessObject?.type === 'custom:connectable' && + // target?.businessObject?.type === 'custom:connectable' + //) { + return { type: 'Connection' }; + // { type: 'Connection' }; // Тип соединения +// } + + return false; // Запретить соединение + }); + } +} diff --git a/src/CustomGlobalConnectRulesModule.ts b/src/CustomGlobalConnectRulesModule.ts new file mode 100644 index 0000000..424e449 --- /dev/null +++ b/src/CustomGlobalConnectRulesModule.ts @@ -0,0 +1,8 @@ +import CustomGlobalConnectRules from './CustomGlobalConnectRules'; + +const CustomGlobalConnectRulesModule = { + __init__: ['customGlobalConnectRules'], + customGlobalConnectRules: ['type', CustomGlobalConnectRules] +}; + +export default CustomGlobalConnectRulesModule; \ No newline at end of file diff --git a/src/CustomOutlineModule.ts b/src/CustomOutlineModule.ts new file mode 100644 index 0000000..7133159 --- /dev/null +++ b/src/CustomOutlineModule.ts @@ -0,0 +1,62 @@ +import { Element } from 'diagram-js/lib/model/Types'; +import { Outline } from 'diagram-js/lib/features/outline/OutlineProvider'; +import OutlineProvider from 'diagram-js/lib/features/outline/OutlineProvider'; +import { + attr as svgAttr, + create as svgCreate} from 'tiny-svg'; + +import Styles from 'diagram-js/lib/draw/Styles'; + +function CustomOutlineProvider(outline:OutlineProvider, styles:Styles) { + this._styles = styles; + outline.registerProvider(this); +} + +CustomOutlineProvider.$inject = [ + 'outline', + 'styles' +]; + +CustomOutlineProvider.prototype.getOutline = function(element:Element) { + if (element.type === 'custom:circle') { + const outline = svgCreate('circle'); + + svgAttr(outline , { + x: `${element.x}`, + y: `${element.y}`, + cx: element.width / 2, + cy: element.height / 2, + r: 60, + fill: "none", + }); + + console.log(outline); + return outline; + } +} + +CustomOutlineProvider.prototype.updateOutline = function(element: Element, outline: Outline) { + if (element.type === 'custom:circle') { + outline = svgCreate('rect'); + + svgAttr(outline , { + x: `${element.x}`, + y: `${element.y}`, + cx: element.width / 2, + cy: element.height / 2, + r: 60, + fill: "none", + }); + } + console.log(outline); + + return false; +} + +const CustomOutlineModule = { + __init__: ['outlineProvider'], + __depends__: [ 'Outline' ], + outlineProvider: ['type', CustomOutlineProvider] +}; + +export default CustomOutlineModule; diff --git a/src/CustomPaletteModule.ts b/src/CustomPaletteModule.ts index e781e44..9c9eb51 100644 --- a/src/CustomPaletteModule.ts +++ b/src/CustomPaletteModule.ts @@ -17,7 +17,7 @@ function PalettePlugin (create: Create, title: 'Hand Tool', action: { click: function() { - console.log("Hello"); + //console.log("Hello"); } } }, @@ -52,9 +52,26 @@ function PalettePlugin (create: Create, } } }, + 'create-device': { + group: 'create', + className: 'icon-create-shape', + title: 'Create Device', + action: { + click: function() { + var shape = elementFactory.createShape({ + width: 100, + height: 80, + canStartConnection:true, + type: 'custom:circle' + }); + console.log(shape.canStartConnection); + create.start(event, shape); + } + } + }, 'create-connection': { group: 'create', - className: 'connection-create-shape', + className: 'icon-connect', title: 'Create Connection', action: { click: (event) => { diff --git a/src/CustomShapeRendererModule.ts b/src/CustomShapeRendererModule.ts new file mode 100644 index 0000000..e5532bb --- /dev/null +++ b/src/CustomShapeRendererModule.ts @@ -0,0 +1,71 @@ +import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer'; +import DefaultRenderer from 'diagram-js/lib/draw/DefaultRenderer'; +import { Shape } from 'diagram-js/lib/model'; +import { assign } from 'min-dash'; +import { + append as svgAppend, + attr as svgAttr, + create as svgCreate +} from 'tiny-svg'; + + + + +const HIGH_PRIORITY = 1500; + +class CustomShapeRenderer extends BaseRenderer { + + static $inject = ['eventBus', 'styles']; + + constructor(eventBus: any, styles: any) { + super(eventBus, HIGH_PRIORITY); + this.styles = styles; + this.SHAPE_STYLE = styles.style({ fill: 'Canvas', stroke: 'CanvasText', strokeWidth: 2 }); + } + + canRender(element: any): boolean { + return element.type === 'custom:circle'; + } + + + drawShape(visuals, element, attrs): SVGElement { + var circle = svgCreate('circle'); + + svgAttr(circle, { + cx: `${element.width / 2}`, + cy: `${element.height / 2 - 52}`, + r: '2.5mm', + fill: "none", + stroke: "CanvasText", + }); + + var line = svgCreate('line'); + svgAttr(line, { + x1: element.width / 2, + x2: element.width / 2, + y1: element.height/2, + y2: element.height/2 - 40 - 2, + stroke: "CanvasText", + + }) + + var g = svgCreate('g'); + svgAppend(g, circle); + svgAppend(g, line); + + svgAttr(g, assign({}, this.SHAPE_STYLE, attrs || {})); + svgAppend(visuals, g); + console.log(visuals); + + return g; + } +} + + +const CustomShapeRendererModule = { + __init__: ['customShapeRenderer'], + customShapeRenderer: ['type', CustomShapeRenderer] +}; + + +export default CustomShapeRendererModule; \ No newline at end of file diff --git a/src/Diagram.svelte b/src/Diagram.svelte index 5b89886..7b7896b 100644 --- a/src/Diagram.svelte +++ b/src/Diagram.svelte @@ -1,5 +1,4 @@
\ No newline at end of file diff --git a/src/ManhattanConnectionModule.ts b/src/ManhattanConnectionModule.ts index e9a6385..05d16e1 100644 --- a/src/ManhattanConnectionModule.ts +++ b/src/ManhattanConnectionModule.ts @@ -17,7 +17,6 @@ export function updateWaypointsByManhattan (connection: Connection, modeling: Mo { x: x2, y: y2 }); const hasChanged = JSON.stringify(connection.waypoints) != JSON.stringify(waypoints); - if (hasChanged) { modeling.updateWaypoints(connection, waypoints) } @@ -25,26 +24,28 @@ export function updateWaypointsByManhattan (connection: Connection, modeling: Mo } function ManhattanLayoutPlugin(eventBus: EventBus, modeling: Modeling) { - eventBus.on('connection.added', (event) => { + eventBus.on('commandStack.connection.create.executed', (event) => { var connection = (event as any).element; - updateWaypointsByManhattan(connection, modeling); - }); + if (connection) { + updateWaypointsByManhattan(connection, modeling); + } + }); - eventBus.on("shape.move.end", (event) => { - var shape = (event as any).shape; - console.log((event as any).shape); - if (shape.incoming) { - shape.incoming.forEach((element: Connection) => { - updateWaypointsByManhattan(element, modeling); - }); - } + + eventBus.on("shape.move.end", (event) => { + var shape = (event as any).shape; + if (shape.incoming) { + shape.incoming.forEach((element: Connection) => { + updateWaypointsByManhattan(element, modeling); + }); + } - if (shape.outgoing) { - shape.outgoing.forEach((element: Connection) => { - updateWaypointsByManhattan(element, modeling); - }); - } - }); + if (shape.outgoing) { + shape.outgoing.forEach((element: Connection) => { + updateWaypointsByManhattan(element, modeling); + }); + } + }); } export default { diff --git a/src/editor.ts b/src/editor.ts index 4c85445..4c823b3 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -17,6 +17,9 @@ import BendpointMoveModule from 'diagram-js/lib/features/bendpoints'; import StyleModule from './StyleModule.ts'; import ManhattanConnectionModule from './ManhattanConnectionModule.ts'; import CustomPaletteModule from './CustomPaletteModule.ts'; +import CustomGlobalConnectRulesModule from './CustomGlobalConnectRulesModule.ts'; +import CustomShapeRendererModule from './CustomShapeRendererModule.ts'; +import CustomOutlineModule from './CustomOutlineModule.ts'; interface EditorOptions { container: HTMLElement; @@ -36,17 +39,22 @@ export default function Editor(options: EditorOptions): Diagram { , ModelingModule , MoveCanvasModule , MoveModule - , OutlineModule + //, OutlineModule , PaletteModule - , ResizeModule + //, ResizeModule , RulesModule , SelectionModule , ZoomScrollModule , StyleModule , ManhattanConnectionModule , CustomPaletteModule + , CustomGlobalConnectRulesModule + , CustomShapeRendererModule + , CustomOutlineModule ]; + + console.log(container); return new Diagram({ canvas: { container diff --git a/src/style.css b/src/style.css index c98830e..09016c3 100644 --- a/src/style.css +++ b/src/style.css @@ -132,4 +132,12 @@ button:focus { .icon-create-shape:hover { background: url('../resources/hovered/icon-create-rect.svg'); +} + +.icon-connect { + background: url('../resources/icon-connect.svg'); +} + +.icon-connect:hover { + background: url('../resources/hovered/icon-connect.svg'); } \ No newline at end of file