first tries on adding MORE shapes to represent true gost fsa
This commit is contained in:
parent
f2a72d5155
commit
392aebe0df
15 changed files with 577 additions and 79 deletions
37
package-lock.json
generated
37
package-lock.json
generated
|
|
@ -8,6 +8,8 @@
|
||||||
"name": "diagram-js-svelte",
|
"name": "diagram-js-svelte",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"choices": "^0.1.3",
|
||||||
|
"choices.js": "^11.0.3",
|
||||||
"diagram-js": "^15.2.4"
|
"diagram-js": "^15.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -884,6 +886,24 @@
|
||||||
"node": ">= 0.4"
|
"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": {
|
"node_modules/clsx": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
|
|
@ -893,6 +913,14 @@
|
||||||
"node": ">=6"
|
"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": {
|
"node_modules/component-event": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/component-event/-/component-event-0.2.1.tgz",
|
"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": "^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": {
|
"node_modules/htm": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
"vite": "^6.0.5"
|
"vite": "^6.0.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"choices.js": "^11.0.3",
|
||||||
"diagram-js": "^15.2.4"
|
"diagram-js": "^15.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
resources/hovered/icon-connect.svg
Normal file
5
resources/hovered/icon-connect.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg fill="AccentColor" height="46" width="46" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 490 490" xml:space="preserve">
|
||||||
|
<polygon points="107.188,404.465 404.465,107.188 490,107.188 490,0 382.813,0 382.813,85.535 85.535,382.813 0,382.813 0,490
|
||||||
|
107.188,490 "/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 345 B |
5
resources/icon-connect.svg
Normal file
5
resources/icon-connect.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg fill="black" height="46" width="46" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 490 490" xml:space="preserve">
|
||||||
|
<polygon points="107.188,404.465 404.465,107.188 490,107.188 490,0 382.813,0 382.813,85.535 85.535,382.813 0,382.813 0,490
|
||||||
|
107.188,490 "/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 339 B |
285
src/AddObjectForm.svelte
Normal file
285
src/AddObjectForm.svelte
Normal file
|
|
@ -0,0 +1,285 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import {
|
||||||
|
create as svgCreate,
|
||||||
|
append as svgAppend
|
||||||
|
} from 'tiny-svg';
|
||||||
|
import Choices from 'choices.js';
|
||||||
|
|
||||||
|
let типОбъекта: 'Прибор' | 'ИсполнительныйМеханизм' = 'Прибор';
|
||||||
|
let фиксация: 'НаМесте' | 'НаЩите' = 'НаМесте';
|
||||||
|
let типПрибора: 'Величина' | 'Мультивеличина' = 'Величина';
|
||||||
|
let величина: 'Напряжение' | 'Температура' = 'Напряжение';
|
||||||
|
let уточнение: 'ИнтегрированиеСуммированиеПоВремени' | 'РазностьПерепад' | null = null;
|
||||||
|
|
||||||
|
interface Функция {
|
||||||
|
тип: string;
|
||||||
|
значение: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let функции: Функция[] = [];
|
||||||
|
|
||||||
|
const функцииПоТипу = {
|
||||||
|
ВыполняемаяФункция: [
|
||||||
|
'Сигнализация',
|
||||||
|
'АвтоматическоеРегулирование',
|
||||||
|
'ВеличинаОтклоненияОтЗаданной',
|
||||||
|
'Регистрация'],
|
||||||
|
ФункциональныйПризнак: [
|
||||||
|
'ЧувствительныйЭлемент',
|
||||||
|
'Преобразование',
|
||||||
|
'ПервичныйПоказывающийПрибор',
|
||||||
|
'СтанцияУправления',
|
||||||
|
'ВключениеОтключениеПереключение',
|
||||||
|
'Преобразование',
|
||||||
|
'VДополнительный',
|
||||||
|
'ВспомогательныеКомпьютерныеУстройства',
|
||||||
|
'ВспомогательныеВычислительноеУстройство',
|
||||||
|
'ZДополнительный']};
|
||||||
|
|
||||||
|
function addFunction() {
|
||||||
|
функции = [...функции, { тип: 'ВыполняемаяФункция', значение: 'Регистрация' }];
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeFunction(index: number) {
|
||||||
|
функции = функции.filter((_, i) => i !== index);
|
||||||
|
}
|
||||||
|
|
||||||
|
let являетсяПаз = false;
|
||||||
|
let ручной = false;
|
||||||
|
let направление: 'Открывается' | 'Закрывается' | 'ОстаётсяНаМесте' | null = null;
|
||||||
|
|
||||||
|
function handleSubmit() {
|
||||||
|
const data =
|
||||||
|
типОбъекта === 'Прибор'
|
||||||
|
? {
|
||||||
|
Прибор: {
|
||||||
|
фиксация,
|
||||||
|
тип_прибора: {
|
||||||
|
[типПрибора]: {
|
||||||
|
величина,
|
||||||
|
уточнение,
|
||||||
|
функции: функции.map((функция) => ({
|
||||||
|
[функция.тип]: функция.значение
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
является_паз: являетсяПаз
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
ИсполнительныйМеханизм: {
|
||||||
|
имеет_ручной: ручной,
|
||||||
|
направление
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(величина);
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
})
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
|
import AddObjectForm from './AddObjectForm.svelte';
|
||||||
import Diagram from './Diagram.svelte';
|
import Diagram from './Diagram.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<h1>FSA Editor</h1>
|
<h1>FSA Editor</h1>
|
||||||
|
<AddObjectForm/>
|
||||||
<Diagram />
|
<Diagram />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
|
||||||
43
src/CustomGlobalConnectRules.ts
Normal file
43
src/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
src/CustomGlobalConnectRulesModule.ts
Normal file
8
src/CustomGlobalConnectRulesModule.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import CustomGlobalConnectRules from './CustomGlobalConnectRules';
|
||||||
|
|
||||||
|
const CustomGlobalConnectRulesModule = {
|
||||||
|
__init__: ['customGlobalConnectRules'],
|
||||||
|
customGlobalConnectRules: ['type', CustomGlobalConnectRules]
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomGlobalConnectRulesModule;
|
||||||
62
src/CustomOutlineModule.ts
Normal file
62
src/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;
|
||||||
|
|
@ -17,7 +17,7 @@ function PalettePlugin (create: Create,
|
||||||
title: 'Hand Tool',
|
title: 'Hand Tool',
|
||||||
action: {
|
action: {
|
||||||
click: function() {
|
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': {
|
'create-connection': {
|
||||||
group: 'create',
|
group: 'create',
|
||||||
className: 'connection-create-shape',
|
className: 'icon-connect',
|
||||||
title: 'Create Connection',
|
title: 'Create Connection',
|
||||||
action: {
|
action: {
|
||||||
click: (event) => {
|
click: (event) => {
|
||||||
|
|
|
||||||
71
src/CustomShapeRendererModule.ts
Normal file
71
src/CustomShapeRendererModule.ts
Normal file
|
|
@ -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;
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { connectPoints } from 'diagram-js/lib/layout/ManhattanLayout';
|
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import Canvas from "diagram-js/lib/core/Canvas";
|
import Canvas from "diagram-js/lib/core/Canvas";
|
||||||
import ElementFactory from 'diagram-js/lib/core/ElementFactory';
|
import ElementFactory from 'diagram-js/lib/core/ElementFactory';
|
||||||
|
|
@ -14,70 +13,16 @@ import { connectPoints } from 'diagram-js/lib/layout/ManhattanLayout';
|
||||||
const canvas = diagram.get<Canvas>("canvas");
|
const canvas = diagram.get<Canvas>("canvas");
|
||||||
const elementFactory = diagram.get<ElementFactory>('elementFactory');
|
const elementFactory = diagram.get<ElementFactory>('elementFactory');
|
||||||
var root = elementFactory.createRoot();
|
var root = elementFactory.createRoot();
|
||||||
|
|
||||||
|
|
||||||
canvas.setRootElement(root);
|
canvas.setRootElement(root);
|
||||||
var shape1 = elementFactory.createShape({
|
|
||||||
x: 150,
|
|
||||||
y: 100,
|
|
||||||
width: 100,
|
|
||||||
height: 80
|
|
||||||
});
|
|
||||||
|
|
||||||
canvas.addShape(shape1, root);
|
|
||||||
|
|
||||||
var shape2 = elementFactory.createShape({
|
|
||||||
x: 290,
|
|
||||||
y: 220,
|
|
||||||
width: 100,
|
|
||||||
height: 80
|
|
||||||
});
|
|
||||||
|
|
||||||
canvas.addShape(shape2, root);
|
|
||||||
|
|
||||||
var shape3 = elementFactory.createShape({
|
|
||||||
x: 450,
|
|
||||||
y: 80,
|
|
||||||
width: 100,
|
|
||||||
height: 80
|
|
||||||
});
|
|
||||||
|
|
||||||
canvas.addShape(shape3, root);
|
|
||||||
|
|
||||||
|
|
||||||
var shape4 = elementFactory.createShape({
|
|
||||||
x: 425,
|
|
||||||
y: 50,
|
|
||||||
width: 300,
|
|
||||||
height: 200,
|
|
||||||
isFrame: true
|
|
||||||
});
|
|
||||||
canvas.addShape(shape4, root);
|
|
||||||
|
|
||||||
const manhattanLayout = connectPoints(
|
|
||||||
{ x: shape1.x + shape1.width / 2, y: shape1.y + shape1.height / 2 },
|
|
||||||
{ x: shape2.x + shape2.width / 2, y: shape2.y + shape2.height / 2 }
|
|
||||||
);
|
|
||||||
var connection1 = elementFactory.createConnection({
|
|
||||||
waypoints: manhattanLayout,
|
|
||||||
source: shape1,
|
|
||||||
target: shape2
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
canvas.addConnection(connection1, root);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.container {
|
.container {
|
||||||
width: 100%;
|
width: 297mm;
|
||||||
height: 500px;
|
height: 210mm;
|
||||||
border: 1px solid #aaa;
|
border: 1px solid #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div bind:this={container} class="container"></div>
|
<div bind:this={container} class="container"></div>
|
||||||
|
|
@ -17,7 +17,6 @@ export function updateWaypointsByManhattan (connection: Connection, modeling: Mo
|
||||||
{ x: x2, y: y2 });
|
{ x: x2, y: y2 });
|
||||||
|
|
||||||
const hasChanged = JSON.stringify(connection.waypoints) != JSON.stringify(waypoints);
|
const hasChanged = JSON.stringify(connection.waypoints) != JSON.stringify(waypoints);
|
||||||
|
|
||||||
if (hasChanged) {
|
if (hasChanged) {
|
||||||
modeling.updateWaypoints(connection, waypoints)
|
modeling.updateWaypoints(connection, waypoints)
|
||||||
}
|
}
|
||||||
|
|
@ -25,26 +24,28 @@ export function updateWaypointsByManhattan (connection: Connection, modeling: Mo
|
||||||
}
|
}
|
||||||
|
|
||||||
function ManhattanLayoutPlugin(eventBus: EventBus, modeling: Modeling) {
|
function ManhattanLayoutPlugin(eventBus: EventBus, modeling: Modeling) {
|
||||||
eventBus.on('connection.added', (event) => {
|
eventBus.on('commandStack.connection.create.executed', (event) => {
|
||||||
var connection = (event as any).element;
|
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;
|
eventBus.on("shape.move.end", (event) => {
|
||||||
console.log((event as any).shape);
|
var shape = (event as any).shape;
|
||||||
if (shape.incoming) {
|
if (shape.incoming) {
|
||||||
shape.incoming.forEach((element: Connection) => {
|
shape.incoming.forEach((element: Connection) => {
|
||||||
updateWaypointsByManhattan(element, modeling);
|
updateWaypointsByManhattan(element, modeling);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shape.outgoing) {
|
if (shape.outgoing) {
|
||||||
shape.outgoing.forEach((element: Connection) => {
|
shape.outgoing.forEach((element: Connection) => {
|
||||||
updateWaypointsByManhattan(element, modeling);
|
updateWaypointsByManhattan(element, modeling);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@ import BendpointMoveModule from 'diagram-js/lib/features/bendpoints';
|
||||||
import StyleModule from './StyleModule.ts';
|
import StyleModule from './StyleModule.ts';
|
||||||
import ManhattanConnectionModule from './ManhattanConnectionModule.ts';
|
import ManhattanConnectionModule from './ManhattanConnectionModule.ts';
|
||||||
import CustomPaletteModule from './CustomPaletteModule.ts';
|
import CustomPaletteModule from './CustomPaletteModule.ts';
|
||||||
|
import CustomGlobalConnectRulesModule from './CustomGlobalConnectRulesModule.ts';
|
||||||
|
import CustomShapeRendererModule from './CustomShapeRendererModule.ts';
|
||||||
|
import CustomOutlineModule from './CustomOutlineModule.ts';
|
||||||
|
|
||||||
interface EditorOptions {
|
interface EditorOptions {
|
||||||
container: HTMLElement;
|
container: HTMLElement;
|
||||||
|
|
@ -36,17 +39,22 @@ export default function Editor(options: EditorOptions): Diagram {
|
||||||
, ModelingModule
|
, ModelingModule
|
||||||
, MoveCanvasModule
|
, MoveCanvasModule
|
||||||
, MoveModule
|
, MoveModule
|
||||||
, OutlineModule
|
//, OutlineModule
|
||||||
, PaletteModule
|
, PaletteModule
|
||||||
, ResizeModule
|
//, ResizeModule
|
||||||
, RulesModule
|
, RulesModule
|
||||||
, SelectionModule
|
, SelectionModule
|
||||||
, ZoomScrollModule
|
, ZoomScrollModule
|
||||||
, StyleModule
|
, StyleModule
|
||||||
, ManhattanConnectionModule
|
, ManhattanConnectionModule
|
||||||
, CustomPaletteModule
|
, CustomPaletteModule
|
||||||
|
, CustomGlobalConnectRulesModule
|
||||||
|
, CustomShapeRendererModule
|
||||||
|
, CustomOutlineModule
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
console.log(container);
|
||||||
return new Diagram({
|
return new Diagram({
|
||||||
canvas: {
|
canvas: {
|
||||||
container
|
container
|
||||||
|
|
|
||||||
|
|
@ -132,4 +132,12 @@ button:focus {
|
||||||
|
|
||||||
.icon-create-shape:hover {
|
.icon-create-shape:hover {
|
||||||
background: url('../resources/hovered/icon-create-rect.svg');
|
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');
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue