Add files via upload
This commit is contained in:
parent
392aebe0df
commit
a3243dd1ba
14 changed files with 871 additions and 0 deletions
271
AddObjectForm.svelte
Normal file
271
AddObjectForm.svelte
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import {
|
||||
create as svgCreate,
|
||||
append as svgAppend
|
||||
} from 'tiny-svg';
|
||||
import { writable } from 'svelte/store';
|
||||
import Choices from 'choices.js';
|
||||
|
||||
let типОбъекта: 'Прибор' | 'ИсполнительныйМеханизм' = 'Прибор';
|
||||
let фиксация: 'НаМесте' | 'НаЩите' = 'НаМесте';
|
||||
let типПрибора: 'Величина' | 'Мультивеличина' = 'Величина';
|
||||
let величина: 'Напряжение' | 'Температура' = 'Напряжение';
|
||||
let уточнение: 'ИнтегрированиеСуммированиеПоВремени' | 'РазностьПерепад' | null = null;
|
||||
|
||||
interface Функция {
|
||||
тип: string;
|
||||
значение: string;
|
||||
}
|
||||
|
||||
let функции: Функция[] = [];
|
||||
|
||||
export const data = writable({'value': svgCreate('g')});
|
||||
|
||||
const функцииПоТипу = {
|
||||
ВыполняемаяФункция: [
|
||||
'Сигнализация',
|
||||
'АвтоматическоеРегулирование',
|
||||
'ВеличинаОтклоненияОтЗаданной',
|
||||
'Регистрация'],
|
||||
ФункциональныйПризнак: [
|
||||
'ЧувствительныйЭлемент',
|
||||
'Преобразование',
|
||||
'ПервичныйПоказывающийПрибор',
|
||||
'СтанцияУправления',
|
||||
'ВключениеОтключениеПереключение',
|
||||
'Преобразование',
|
||||
'VДополнительный',
|
||||
'ВспомогательныеКомпьютерныеУстройства',
|
||||
'ВспомогательныеВычислительноеУстройство',
|
||||
'ZДополнительный']};
|
||||
|
||||
function addFunction() {
|
||||
функции = [...функции, { тип: 'ВыполняемаяФункция', значение: 'Регистрация' }];
|
||||
}
|
||||
|
||||
function removeFunction(index: number) {
|
||||
функции = функции.filter((_, i) => i !== index);
|
||||
}
|
||||
|
||||
let являетсяПаз = false;
|
||||
let ручной = false;
|
||||
let направление: 'Открывается' | 'Закрывается' | 'ОстаётсяНаМесте' | null = null;
|
||||
|
||||
|
||||
function handleSubmit() {
|
||||
|
||||
data.update(() => ({value: to_svg(0, 0)}));
|
||||
|
||||
}
|
||||
|
||||
function to_svg(x, y) {
|
||||
const r = svgCreate('g');
|
||||
if (типОбъекта === 'ИсполнительныйМеханизм') {
|
||||
var circle = svgCreate('circle',
|
||||
{
|
||||
cx: x,
|
||||
cy: y - 52,
|
||||
r: '2.5mm',
|
||||
fill: "none",
|
||||
stroke: "CanvasText",
|
||||
});
|
||||
|
||||
var line = svgCreate('line',
|
||||
{
|
||||
x1: x,
|
||||
x2: x,
|
||||
y1: y,
|
||||
y2: y - 42,
|
||||
stroke: "CanvasText",
|
||||
})
|
||||
|
||||
var h = svgCreate('text',
|
||||
x: x,
|
||||
y: y,
|
||||
|
||||
)
|
||||
|
||||
svgAppend(r, circle);
|
||||
svgAppend(r, line); // здесь НЕОБХОДИМО добавить стрелки в разных направлениях TODO
|
||||
return r;
|
||||
}
|
||||
|
||||
if (являетсяПаз) {
|
||||
const w = 10;
|
||||
const h = 10;
|
||||
const outer = svgCreate('polygon', {points: `${x},${y+h} ${x+w},${y} ${x},${y-h} ${x-w},${y}`, stroke:"CanvasText", fill:"Canvas"});
|
||||
svgAppend(r, outer);
|
||||
const rect = svgCreate('rect', {x: x-w/2, y: y-h/2, width:w, height: h, stroke:"CanvasText", fill:"Canvas"})
|
||||
svgAppend(r, rect);
|
||||
} else {
|
||||
const circle = svgCreate('circle', {x: x, y: y, r: "5mm", stroke:"CanvasText", fill:"Canvas"});
|
||||
svgAppend(r, circle);
|
||||
}
|
||||
if (фиксация == "НаЩите") {
|
||||
const h = svgCreate('line', {x0: x - 5, y0: y, x1: x + 5, y1: y, stroke:"CanvasText"})
|
||||
svgAppend(r, h);
|
||||
}
|
||||
|
||||
var toText = величина ; // TODO + что-то ещё
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
const element = document.getElementById('choices-select');
|
||||
console.log(element);
|
||||
if (element !== null) {
|
||||
const choices = new Choices(element, {
|
||||
searchEnabled: true, // Включить поиск
|
||||
shouldSort: false, // Отключить сортировку (по умолчанию элементы остаются в заданном порядке)
|
||||
placeholder: true, // Включить плейсхолдер (если нужен)
|
||||
placeholderValue: 'Выберите величину', // Текст плейсхолдера
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<label>
|
||||
<span>Тип объекта:</span>
|
||||
<select bind:value={типОбъекта}>
|
||||
<option value="Прибор">Прибор</option>
|
||||
<option value="ИсполнительныйМеханизм">Исполнительный механизм</option>
|
||||
</select>
|
||||
</label>
|
||||
<br/>
|
||||
|
||||
{#if типОбъекта === 'Прибор'}
|
||||
<label>
|
||||
<span>Фиксация:</span>
|
||||
<select bind:value={фиксация}>
|
||||
<option value="НаМесте">На месте</option>
|
||||
<option value="НаЩите">На щите</option>
|
||||
</select>
|
||||
</label>
|
||||
<br/>
|
||||
|
||||
<label>
|
||||
<span>Тип прибора:</span>
|
||||
<select bind:value={типПрибора}>
|
||||
<option value="Величина">Величина</option>
|
||||
<option value="Мультивеличина">Мультивеличина</option>
|
||||
</select>
|
||||
</label>
|
||||
<br/>
|
||||
|
||||
<label>
|
||||
<span>Величина:</span>
|
||||
<select id="choices-select" bind:value={величина}>
|
||||
<option value="A">Анализ, качество</option>
|
||||
<option value="B">Пламя, горение</option>
|
||||
<option value="C">Дополнительная величина</option>
|
||||
<option value="D">Дополнительная величина</option>
|
||||
<option value="E">Напряжение</option>
|
||||
<option value="F">Расход</option>
|
||||
<option value="G">Дополнительная величина</option>
|
||||
<option value="H">Ручное воздействие</option>
|
||||
<option value="I">Ток</option>
|
||||
<option value="J">Мощность</option>
|
||||
<option value="K">Время</option>
|
||||
<option value="L">Уровень</option>
|
||||
<option value="M">Дополнительная величина</option>
|
||||
<option value="N">Дополнительная величина</option>
|
||||
<option value="O">Дополнительная величина</option>
|
||||
<option value="P">Давление</option>
|
||||
<option value="Q">Количество</option>
|
||||
<option value="E">Радиоактивность</option>
|
||||
<option value="S">Скорость, частота</option>
|
||||
<option value="T">Температура</option>
|
||||
<option value="U">Разнородные величины</option> // несколько величин ТОЛЬКО здесь
|
||||
<option value="V">Вибрация</option>
|
||||
<option value="W">Вес</option>
|
||||
<option value="X">Дополнительная величина (нерекомендованная буква)</option>
|
||||
<option value="Y">Событие</option>
|
||||
<option value="Z">Размер</option>
|
||||
</select>
|
||||
</label>
|
||||
<br/>
|
||||
|
||||
<label>
|
||||
<span>Уточнение:</span>
|
||||
<select bind:value={уточнение}>
|
||||
<option value="ИнтегрированиеСуммированиеПоВремени">Интегрирование</option>
|
||||
<option value="РазностьПерепад">Разность</option>
|
||||
<option value={null}>Без уточнения</option>
|
||||
</select>
|
||||
</label>
|
||||
<br/>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" bind:checked={являетсяПаз} />
|
||||
<span>Является паз</span>
|
||||
</label>
|
||||
<br/>
|
||||
|
||||
<strong>Функции<button type="button" on:click={addFunction} class="simplebutton">+</button></strong>
|
||||
{#each функции as функция, i}
|
||||
<div class="функция-элемент" style="margin-bottom: 10px;">
|
||||
<label>
|
||||
Тип функции:
|
||||
<select bind:value={функция.тип}>
|
||||
<option value="ВыполняемаяФункция">Выполняемая функция</option>
|
||||
<option value="ФункциональныйПризнак">Функциональный признак</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Значение:
|
||||
<select bind:value={функция.значение}>
|
||||
{#if функция.тип === 'ВыполняемаяФункция'}
|
||||
{#each функцииПоТипу.ВыполняемаяФункция as val}
|
||||
<option value={val}>{val}</option>
|
||||
{/each}
|
||||
{/if}
|
||||
{#if функция.тип === 'ФункциональныйПризнак'}
|
||||
{#each функцииПоТипу.ФункциональныйПризнак as val}
|
||||
<option value={val}>{val}</option>
|
||||
{/each}
|
||||
{/if}
|
||||
</select>
|
||||
</label>
|
||||
<button type="button" on:click={() => removeFunction(i)} class="simplebutton">-</button>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
|
||||
{:else}
|
||||
<label>
|
||||
<span>Имеет ручное управление:</span>
|
||||
<input type="checkbox" bind:checked={ручной} />
|
||||
</label>
|
||||
<br/>
|
||||
|
||||
<label>
|
||||
<span>Направление:</span>
|
||||
<select bind:value={направление}>
|
||||
<option value="Открывается">Открывается</option>
|
||||
<option value="Закрывается">Закрывается</option>
|
||||
<option value="ОстаётсяНаМесте">Остаётся на месте</option>
|
||||
<option value={null}>Не указано</option>
|
||||
</select>
|
||||
</label>
|
||||
<br/>
|
||||
{/if}
|
||||
<br/>
|
||||
<button on:click={handleSubmit}>OK</button>
|
||||
<br/>
|
||||
</div>
|
||||
<style>
|
||||
.simplebutton {
|
||||
width: 40px; /* Ширина кнопки */
|
||||
height: 40px; /* Высота кнопки должна совпадать с шириной */
|
||||
border: 1px solid lightgray;
|
||||
margin-left: 5px;
|
||||
border-radius: 50%; /* Делает кнопку круглой */
|
||||
display: inline-flex; /* Для центрирования содержимого */
|
||||
justify-content: center; /* Горизонтальное центрирование */
|
||||
align-items: center; /* Вертикальное центрирование */
|
||||
cursor: pointer; /* Изменение курсора */
|
||||
}
|
||||
</style>
|
||||
17
App.svelte
Normal file
17
App.svelte
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<script>
|
||||
import AddObjectForm from './AddObjectForm.svelte';
|
||||
import Diagram from './Diagram.svelte';
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h1>FSA Editor</h1>
|
||||
<AddObjectForm/>
|
||||
<Diagram />
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 1rem;
|
||||
}
|
||||
</style>
|
||||
43
CustomGlobalConnectRules.ts
Normal file
43
CustomGlobalConnectRules.ts
Normal file
|
|
@ -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; // Запретить соединение
|
||||
});
|
||||
}
|
||||
}
|
||||
8
CustomGlobalConnectRulesModule.ts
Normal file
8
CustomGlobalConnectRulesModule.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import CustomGlobalConnectRules from './CustomGlobalConnectRules';
|
||||
|
||||
const CustomGlobalConnectRulesModule = {
|
||||
__init__: ['customGlobalConnectRules'],
|
||||
customGlobalConnectRules: ['type', CustomGlobalConnectRules]
|
||||
};
|
||||
|
||||
export default CustomGlobalConnectRulesModule;
|
||||
62
CustomOutlineModule.ts
Normal file
62
CustomOutlineModule.ts
Normal file
|
|
@ -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;
|
||||
89
CustomPaletteModule.ts
Normal file
89
CustomPaletteModule.ts
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import ElementFactory from "diagram-js/lib/core/ElementFactory";
|
||||
import Palette from "diagram-js/lib/features/palette/Palette";
|
||||
import LassoTool from "diagram-js/lib/features/lasso-tool/LassoTool";
|
||||
import Create from "diagram-js/lib/features/create/Create";
|
||||
import GlobalConnect from "diagram-js/lib/features/global-connect/GlobalConnect";
|
||||
|
||||
function PalettePlugin (create: Create,
|
||||
elementFactory:ElementFactory,
|
||||
globalConnect: GlobalConnect,
|
||||
lassoTool: LassoTool,
|
||||
palette: Palette) {
|
||||
palette.registerProvider({
|
||||
getPaletteEntries: () => ({
|
||||
'hand-tool': {
|
||||
group: 'tools',
|
||||
className: 'icon-hand-tool',
|
||||
title: 'Hand Tool',
|
||||
action: {
|
||||
click: function() {
|
||||
//console.log("Hello");
|
||||
}
|
||||
}
|
||||
},
|
||||
'lasso-tool': {
|
||||
group: 'tools',
|
||||
className: 'icon-lasso-tool',
|
||||
title: 'Lasso Tool',
|
||||
action: {
|
||||
click: function(event) {
|
||||
lassoTool.activateSelection(event as MouseEvent);
|
||||
}
|
||||
}
|
||||
},
|
||||
'tool-separator': {
|
||||
group: 'tools',
|
||||
separator: true,
|
||||
action: {}
|
||||
},
|
||||
'create-shape': {
|
||||
group: 'create',
|
||||
className: 'icon-create-shape',
|
||||
title: 'Create Shape',
|
||||
action: {
|
||||
click: function() {
|
||||
var shape = elementFactory.createShape({
|
||||
width: 100,
|
||||
height: 80,
|
||||
canStartConnection:true
|
||||
});
|
||||
console.log(shape.canStartConnection);
|
||||
create.start(event, shape);
|
||||
}
|
||||
}
|
||||
},
|
||||
'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: 'icon-connect',
|
||||
title: 'Create Connection',
|
||||
action: {
|
||||
click: (event) => {
|
||||
globalConnect.start(event, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
__init__: [ 'palettePlugin' ],
|
||||
palettePlugin: [ 'type', PalettePlugin ]
|
||||
};
|
||||
67
CustomShapeRendererModule.ts
Normal file
67
CustomShapeRendererModule.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
|
||||
import { assign } from 'min-dash';
|
||||
import {
|
||||
append as svgAppend,
|
||||
attr as svgAttr,
|
||||
create as svgCreate
|
||||
} from 'tiny-svg';
|
||||
import { data } from './AddObjectForm.svelte';
|
||||
|
||||
|
||||
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 {
|
||||
console.log(data);
|
||||
var circle = svgCreate('circle');
|
||||
|
||||
svgAttr(circle, {
|
||||
cx: `${element.width / 2}`,
|
||||
cy: `${element.height / 2 - 40}`,
|
||||
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 - 30 - 2,
|
||||
stroke: "CanvasText",
|
||||
|
||||
})
|
||||
|
||||
var g = svgCreate('g');
|
||||
svgAppend(g, circle);
|
||||
svgAppend(g, line);
|
||||
|
||||
svgAttr(g, assign({}, this.SHAPE_STYLE, attrs || {}));
|
||||
svgAppend(visuals, g);
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const CustomShapeRendererModule = {
|
||||
__init__: ['customShapeRenderer'],
|
||||
customShapeRenderer: ['type', CustomShapeRenderer]
|
||||
};
|
||||
|
||||
|
||||
export default CustomShapeRendererModule;
|
||||
28
Diagram.svelte
Normal file
28
Diagram.svelte
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import Canvas from "diagram-js/lib/core/Canvas";
|
||||
import ElementFactory from 'diagram-js/lib/core/ElementFactory';
|
||||
import Editor from './editor.ts'
|
||||
import 'diagram-js/assets/diagram-js.css';
|
||||
|
||||
let container: HTMLDivElement | null = null;
|
||||
|
||||
onMount(() => {
|
||||
if (container === null) return;
|
||||
const diagram = Editor({ container });
|
||||
const canvas = diagram.get<Canvas>("canvas");
|
||||
const elementFactory = diagram.get<ElementFactory>('elementFactory');
|
||||
var root = elementFactory.createRoot();
|
||||
canvas.setRootElement(root);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
width: 297mm;
|
||||
height: 210mm;
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div bind:this={container} class="container"></div>
|
||||
54
ManhattanConnectionModule.ts
Normal file
54
ManhattanConnectionModule.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
import { connectPoints } from 'diagram-js/lib/layout/ManhattanLayout';
|
||||
import Modeling from 'diagram-js/lib/features/modeling/Modeling';
|
||||
import EventBus from 'diagram-js/lib/core/EventBus';
|
||||
import { Connection } from 'diagram-js/lib/model/Types';
|
||||
|
||||
export function updateWaypointsByManhattan (connection: Connection, modeling: Modeling ): void {
|
||||
if (connection.source && connection.target) {
|
||||
const x0 = connection.source.x + connection.source.width / 2;
|
||||
const x1 = connection.target.x + connection.target.width / 2;
|
||||
const y0 = connection.source.y + connection.source.height / 2;
|
||||
const y1 = connection.target.y + connection.target.height / 2;
|
||||
const x2 = (Math.abs(x0-x1) < 5) ? x0 : x1;
|
||||
const y2 = (Math.abs(y0-y1) < 5) ? y0 : y1;
|
||||
const waypoints = connectPoints(
|
||||
{ x: x0, y: y0 },
|
||||
{ x: x2, y: y2 });
|
||||
|
||||
const hasChanged = JSON.stringify(connection.waypoints) != JSON.stringify(waypoints);
|
||||
if (hasChanged) {
|
||||
modeling.updateWaypoints(connection, waypoints)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ManhattanLayoutPlugin(eventBus: EventBus, modeling: Modeling) {
|
||||
eventBus.on('commandStack.connection.create.executed', (event) => {
|
||||
var connection = (event as any).element;
|
||||
if (connection) {
|
||||
updateWaypointsByManhattan(connection, 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);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
__init__: [ 'manhattanLayoutPlugin' ],
|
||||
manhattanLayoutPlugin: [ 'type', ManhattanLayoutPlugin ]
|
||||
};
|
||||
11
StyleModule.ts
Normal file
11
StyleModule.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
export default {
|
||||
__init__: ['customRenderer'],
|
||||
customRenderer: [
|
||||
'type',
|
||||
function (defaultRenderer: any) {
|
||||
defaultRenderer.CONNECTION_STYLE = { fill: 'none', strokeWidth: 5, stroke: 'CanvasText' };
|
||||
defaultRenderer.SHAPE_STYLE = { fill: 'Canvas', stroke: 'CanvasText', strokeWidth: 2 };
|
||||
defaultRenderer.FRAME_STYLE = { fill: 'none', stroke: 'CanvasText', strokeDasharray: 4, strokeWidth: 2 };
|
||||
}
|
||||
]
|
||||
};
|
||||
64
editor.ts
Normal file
64
editor.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import Diagram from 'diagram-js';
|
||||
import ConnectModule from 'diagram-js/lib/features/connect';
|
||||
import ContextPadModule from 'diagram-js/lib/features/context-pad';
|
||||
import CreateModule from 'diagram-js/lib/features/create';
|
||||
import LassoToolModule from 'diagram-js/lib/features/lasso-tool';
|
||||
import ModelingModule from 'diagram-js/lib/features/modeling';
|
||||
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
|
||||
import MoveModule from 'diagram-js/lib/features/move';
|
||||
import OutlineModule from 'diagram-js/lib/features/outline';
|
||||
import PaletteModule from 'diagram-js/lib/features/palette';
|
||||
import ResizeModule from 'diagram-js/lib/features/resize';
|
||||
import RulesModule from 'diagram-js/lib/features/rules';
|
||||
import SelectionModule from 'diagram-js/lib/features/selection';
|
||||
import GlobalConnectModule from 'diagram-js/lib/features/global-connect';
|
||||
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
|
||||
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;
|
||||
additionalModules?: Array<any>;
|
||||
}
|
||||
|
||||
export default function Editor(options: EditorOptions): Diagram {
|
||||
const { container } = options;
|
||||
|
||||
const modules = [
|
||||
BendpointMoveModule
|
||||
, ConnectModule
|
||||
, ContextPadModule
|
||||
, CreateModule
|
||||
, GlobalConnectModule
|
||||
, LassoToolModule
|
||||
, ModelingModule
|
||||
, MoveCanvasModule
|
||||
, MoveModule
|
||||
//, OutlineModule
|
||||
, PaletteModule
|
||||
//, ResizeModule
|
||||
, RulesModule
|
||||
, SelectionModule
|
||||
, ZoomScrollModule
|
||||
, StyleModule
|
||||
, ManhattanConnectionModule
|
||||
, CustomPaletteModule
|
||||
, CustomGlobalConnectRulesModule
|
||||
, CustomShapeRendererModule
|
||||
, CustomOutlineModule
|
||||
];
|
||||
|
||||
|
||||
console.log(container);
|
||||
return new Diagram({
|
||||
canvas: {
|
||||
container
|
||||
},
|
||||
modules: modules
|
||||
});
|
||||
}
|
||||
13
main.ts
Normal file
13
main.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { mount } from 'svelte'
|
||||
import App from './App.svelte';
|
||||
|
||||
const target = document.getElementById('app');
|
||||
|
||||
if (!target) {
|
||||
throw new Error("Target element with ID 'app' not found in DOM.");
|
||||
}
|
||||
|
||||
const app = mount(App, {
|
||||
target: document.getElementById('app')!,
|
||||
})
|
||||
export default app;
|
||||
143
style.css
Normal file
143
style.css
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
:root {
|
||||
color: CanvasText;
|
||||
background-color: Canvas;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: ButtonFace;
|
||||
color: ButtonText;
|
||||
border-color: ButtonBorder;
|
||||
}
|
||||
button:hover {
|
||||
border-color: AccentColor;
|
||||
}
|
||||
button:focus {
|
||||
outline: 4px auto Highlight;
|
||||
}
|
||||
|
||||
.anchor {
|
||||
background-color: AccentColor;
|
||||
color: AccentColorText;
|
||||
visibility: hidden;
|
||||
transition: visibility 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color: CanvasText;
|
||||
background-color: Canvas;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
|
||||
--primary-color: CanvasText;
|
||||
--hover-color: #747bff;
|
||||
--background-color: #242424;
|
||||
--background-light: #ffffff;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: var(--background-color);
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: var(--background-color);
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
button:focus {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
.svgContainer {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: var(--background-color);
|
||||
background-color: var(--background-light);
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
button:hover {
|
||||
border-color: var(--hover-color);
|
||||
}
|
||||
}
|
||||
|
||||
.svgContainer {
|
||||
border: solid CanvasText 1px;
|
||||
}
|
||||
|
||||
.icon-hand-tool {
|
||||
background: url('../resources/icon-hand-tool.svg');
|
||||
}
|
||||
|
||||
.icon-lasso-tool {
|
||||
background: url('../resources/icon-lasso-tool.svg');
|
||||
}
|
||||
|
||||
.icon-hand-tool:hover {
|
||||
background: url('../resources/hovered/icon-hand-tool.svg');
|
||||
}
|
||||
|
||||
.icon-lasso-tool:hover {
|
||||
background: url('../resources/hovered/icon-lasso-tool.svg');
|
||||
}
|
||||
|
||||
.pad-icon-remove {
|
||||
background: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20width%3D%2246%22%20height%3D%2246%22%3E%3Cline%20x1%3D%225%22%20y1%3D%225%22%20x2%3D%2215%22%20y2%3D%2215%22%2F%3E%3Cline%20x1%3D%2215%22%20y1%3D%225%22%20x2%3D%225%22%20y2%3D%2215%22%2F%3E%3C%2Fsvg%3E') !important;
|
||||
}
|
||||
|
||||
.pad-icon-connect {
|
||||
background: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.5%22%20width%3D%2246%22%20height%3D%2246%22%3E%3Cline%20x1%3D%2215%22%20y1%3D%225%22%20x2%3D%225%22%20y2%3D%2215%22%2F%3E%3C%2Fsvg%3E') !important;
|
||||
}
|
||||
|
||||
.icon-create-shape {
|
||||
background: url('../resources/icon-create-rect.svg');
|
||||
}
|
||||
|
||||
.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');
|
||||
}
|
||||
1
vite-env.d.ts
vendored
Normal file
1
vite-env.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
||||
Loading…
Add table
Add a link
Reference in a new issue