From 40c5d319ee0c9db2f44da82bdd913303078f3004 Mon Sep 17 00:00:00 2001 From: bryzZz Date: Mon, 9 Oct 2023 20:28:17 +0800 Subject: [PATCH 01/10] try state nesting --- src/renderer/src/lib/data/StateMachine.ts | 3 ++ src/renderer/src/lib/drawable/Draggable.ts | 2 + src/renderer/src/lib/drawable/State.ts | 20 +++++++- src/renderer/src/lib/drawable/States.ts | 60 ++++++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/lib/data/StateMachine.ts b/src/renderer/src/lib/data/StateMachine.ts index a1be0da9d..048212acb 100644 --- a/src/renderer/src/lib/data/StateMachine.ts +++ b/src/renderer/src/lib/data/StateMachine.ts @@ -247,8 +247,10 @@ export class StateMachine extends EventEmitter { if (!parent || !child) return; + let numberOfConnectedActions = 0; if (child.data.parent) { this.unlinkState(childId, canUndo); + numberOfConnectedActions += 1; } // Вычисляем новую координату внутри контейнера @@ -268,6 +270,7 @@ export class StateMachine extends EventEmitter { this.undoRedo.do({ type: 'linkState', args: { parentId, childId }, + numberOfConnectedActions, }); if (addOnceOff) { child.addOnceOff('dragend'); // Линковка состояния меняет его позицию и это плохо для undo diff --git a/src/renderer/src/lib/drawable/Draggable.ts b/src/renderer/src/lib/drawable/Draggable.ts index 0de7bcc83..1e5563d64 100644 --- a/src/renderer/src/lib/drawable/Draggable.ts +++ b/src/renderer/src/lib/drawable/Draggable.ts @@ -242,6 +242,8 @@ export abstract class Draggable extends EventEmitter { // this.bounds.y = Math.max(0, this.bounds.y); } + this.emit('drag', { event: e, target: this }); + document.body.style.cursor = 'grabbing'; this.container.isDirty = true; }; diff --git a/src/renderer/src/lib/drawable/State.ts b/src/renderer/src/lib/drawable/State.ts index 467194a1a..9bf6db0ec 100644 --- a/src/renderer/src/lib/drawable/State.ts +++ b/src/renderer/src/lib/drawable/State.ts @@ -1,10 +1,11 @@ +import theme, { getColor } from '@renderer/theme'; + import { Draggable } from './Draggable'; import { EdgeHandlers } from './EdgeHandlers'; import { Events } from './Events'; import { picto } from './Picto'; import { Container } from '../basic/Container'; -import theme from '@renderer/theme'; const style = theme.colors.diagram.state; @@ -77,6 +78,10 @@ export class State extends Draggable { this.drawSelection(ctx); this.edgeHandlers.draw(ctx); } + + if (this.container.states.dragInfo?.parentId === this.id) { + this.drawHighlight(ctx); + } } //Прорисовка блока состояния @@ -191,6 +196,19 @@ export class State extends Draggable { */ } + private drawHighlight(ctx: CanvasRenderingContext2D) { + const { x, y, width, height, childrenHeight } = this.drawBounds; + ctx.canvas.hidden; + + ctx.lineWidth = 2; + ctx.strokeStyle = getColor('primaryActive'); + + ctx.beginPath(); + ctx.roundRect(x, y, width, height + childrenHeight, 6 / this.container.app.manager.data.scale); + ctx.stroke(); + ctx.closePath(); + } + //Дополнять внешними border при добавлении дочерних состояний private drawChildren(ctx: CanvasRenderingContext2D, _canvas: HTMLCanvasElement) { if (this.children.size === 0) return; diff --git a/src/renderer/src/lib/drawable/States.ts b/src/renderer/src/lib/drawable/States.ts index 2436c8f4e..0bc1e80e1 100644 --- a/src/renderer/src/lib/drawable/States.ts +++ b/src/renderer/src/lib/drawable/States.ts @@ -13,6 +13,11 @@ type MenuCallback = (state: State, pos: Point) => void; type CreateEventCallback = (state: State, events: EventSelection, click: boolean) => void; type MenuEventCallback = (state: State, position: Point, events: EventSelection) => void; +type DragInfo = { + parentId: string; + childId: string; +} | null; + /** * Контроллер {@link State|состояний}. * Предоставляет подписку на события, связанные с состояниями. @@ -20,12 +25,14 @@ type MenuEventCallback = (state: State, position: Point, events: EventSelection) */ export class States extends EventEmitter { container!: Container; + dragInfo: DragInfo = null; constructor(container: Container) { super(); this.container = container; } + // TODO Переделать это на EventEmitter createCallback!: CreateCallback; createNameCallback!: CreateNameCallback; changeEventCallback!: CreateEventCallback; @@ -130,7 +137,58 @@ export class States extends EventEmitter { // TODO: визуальная обратная связь }; + handleDrag = (e: { event: MyMouseEvent; target: State }) => { + const { target: state } = e; + const position = { x: e.event.x, y: e.event.y }; + + // Чтобы проверять начиная со своего уровня вложенности + const dragOverStates = ( + state.parent ? state.parent.children : this.container.machine.states + ) as Map; + + let possibleParent: State | undefined = undefined; + for (const item of dragOverStates.values()) { + if (state.id == item.id) continue; + if (item.isUnderMouse(position, true)) { + if (typeof possibleParent === 'undefined') { + possibleParent = item; + } else { + // учитываем вложенность, нужно поместить состояние + // в максимально дочернее + let searchPending = true; + while (searchPending) { + searchPending = false; + for (const child of possibleParent.children.values()) { + if (!(child instanceof State)) continue; + if (state.id == child.id) continue; + if (child.isUnderMouse(position, true)) { + possibleParent = child as State; + searchPending = true; + break; + } + } + } + } + } + } + + this.dragInfo = null; + + if (possibleParent) { + this.dragInfo = { + parentId: possibleParent.id, + childId: state.id, + }; + } + }; + handleDragEnd = (e: { target: State; dragStartPosition: Point; dragEndPosition: Point }) => { + if (this.dragInfo) { + this.container.machine.linkState(this.dragInfo.parentId, this.dragInfo.childId); + this.dragInfo = null; + return; + } + this.container.machine.changeStatePosition(e.target.id, e.dragStartPosition, e.dragEndPosition); }; @@ -141,6 +199,7 @@ export class States extends EventEmitter { state.on('contextmenu', this.handleContextMenu as any); state.on('longpress', this.handleLongPress as any); state.on('dragend', this.handleDragEnd as any); + state.on('drag', this.handleDrag as any); state.edgeHandlers.onStartNewTransition = this.handleStartNewTransition; } @@ -152,6 +211,7 @@ export class States extends EventEmitter { state.off('contextmenu', this.handleContextMenu as any); state.off('longpress', this.handleLongPress as any); state.off('dragend', this.handleDragEnd as any); + state.off('drag', this.handleDrag as any); state.edgeHandlers.unbindEvents(); state.unbindEvents(); From 890181f4e194c5e420f05f60b9e8027758efe1e5 Mon Sep 17 00:00:00 2001 From: bryzZz Date: Mon, 9 Oct 2023 20:34:22 +0800 Subject: [PATCH 02/10] delete longpress state linking --- src/renderer/src/lib/drawable/States.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/renderer/src/lib/drawable/States.ts b/src/renderer/src/lib/drawable/States.ts index 0bc1e80e1..bfba06105 100644 --- a/src/renderer/src/lib/drawable/States.ts +++ b/src/renderer/src/lib/drawable/States.ts @@ -123,20 +123,6 @@ export class States extends EventEmitter { } }; - handleLongPress = (e: { target: State; event: MyMouseEvent }) => { - e.event.stopPropagation(); - - // если состояние вложено – отсоединяем - if (typeof e.target.parent !== 'undefined') { - this.container.machine.unlinkState(e.target.id!); - return; - } - - // если под курсором есть состояние – присоединить к нему - this.container.machine.linkStateByPoint(e.target, e.event); - // TODO: визуальная обратная связь - }; - handleDrag = (e: { event: MyMouseEvent; target: State }) => { const { target: state } = e; const position = { x: e.event.x, y: e.event.y }; @@ -197,7 +183,6 @@ export class States extends EventEmitter { state.on('click', this.handleStateClick as any); state.on('dblclick', this.handleStateDoubleClick as any); state.on('contextmenu', this.handleContextMenu as any); - state.on('longpress', this.handleLongPress as any); state.on('dragend', this.handleDragEnd as any); state.on('drag', this.handleDrag as any); @@ -209,7 +194,6 @@ export class States extends EventEmitter { state.off('click', this.handleStateClick as any); state.off('dblclick', this.handleStateDoubleClick as any); state.off('contextmenu', this.handleContextMenu as any); - state.off('longpress', this.handleLongPress as any); state.off('dragend', this.handleDragEnd as any); state.off('drag', this.handleDrag as any); From 2c9e745171472e84e5aa6d47818b3ec7b276a3c0 Mon Sep 17 00:00:00 2001 From: bryzZz Date: Tue, 10 Oct 2023 17:09:39 +0800 Subject: [PATCH 03/10] remove undoRedo fix --- src/renderer/src/lib/data/StateMachine.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/renderer/src/lib/data/StateMachine.ts b/src/renderer/src/lib/data/StateMachine.ts index 048212acb..a1be0da9d 100644 --- a/src/renderer/src/lib/data/StateMachine.ts +++ b/src/renderer/src/lib/data/StateMachine.ts @@ -247,10 +247,8 @@ export class StateMachine extends EventEmitter { if (!parent || !child) return; - let numberOfConnectedActions = 0; if (child.data.parent) { this.unlinkState(childId, canUndo); - numberOfConnectedActions += 1; } // Вычисляем новую координату внутри контейнера @@ -270,7 +268,6 @@ export class StateMachine extends EventEmitter { this.undoRedo.do({ type: 'linkState', args: { parentId, childId }, - numberOfConnectedActions, }); if (addOnceOff) { child.addOnceOff('dragend'); // Линковка состояния меняет его позицию и это плохо для undo From a4b62c6fdc0992700e8a643a3857c7c9fde8ade3 Mon Sep 17 00:00:00 2001 From: bryzZz Date: Tue, 10 Oct 2023 18:05:36 +0800 Subject: [PATCH 04/10] cut off link state by point, change Container events to eventEmitter --- src/renderer/src/components/DiagramEditor.tsx | 5 +- .../src/hooks/useDiagramContextMenu.ts | 3 +- src/renderer/src/lib/basic/Container.ts | 56 +++++++++---------- src/renderer/src/lib/data/StateMachine.ts | 37 ------------ 4 files changed, 32 insertions(+), 69 deletions(-) diff --git a/src/renderer/src/components/DiagramEditor.tsx b/src/renderer/src/components/DiagramEditor.tsx index cd40c8de3..22cc07b7e 100644 --- a/src/renderer/src/components/DiagramEditor.tsx +++ b/src/renderer/src/components/DiagramEditor.tsx @@ -8,6 +8,7 @@ import { EventSelection } from '@renderer/lib/drawable/Events'; import { State } from '@renderer/lib/drawable/State'; import { Transition } from '@renderer/lib/drawable/Transition'; import { Action } from '@renderer/types/diagram'; +import { Point } from '@renderer/types/graphics'; import { CreateModal, CreateModalResult } from './CreateModal'; import { DiagramContextMenu } from './DiagramContextMenu'; @@ -61,8 +62,8 @@ export const DiagramEditor: React.FC = ({ manager, editor, s setNewTransition(undefined); }; - //Перетаскиваем компонент в редактор - editor.container.onStateDrop((position) => { + editor.container.on('dblclick', (e) => { + const position = e as Point; editor?.container.machine.createState({ name: 'Состояние', position, placeInCenter: true }); }); diff --git a/src/renderer/src/hooks/useDiagramContextMenu.ts b/src/renderer/src/hooks/useDiagramContextMenu.ts index 2f05aecf7..12abe4795 100644 --- a/src/renderer/src/hooks/useDiagramContextMenu.ts +++ b/src/renderer/src/hooks/useDiagramContextMenu.ts @@ -31,7 +31,8 @@ export const useDiagramContextMenu = (editor: CanvasEditor | null, manager: Edit }; // контекстное меню для пустого поля - editor.container.onFieldContextMenu((pos) => { + editor.container.on('contextmenu', (e) => { + const pos = e as Point; const canvasPos = editor.container.relativeMousePos(pos); handleEvent(pos, [ diff --git a/src/renderer/src/lib/basic/Container.ts b/src/renderer/src/lib/basic/Container.ts index 5b5ef877f..0e0c213a6 100644 --- a/src/renderer/src/lib/basic/Container.ts +++ b/src/renderer/src/lib/basic/Container.ts @@ -2,6 +2,7 @@ import { getColor } from '@renderer/theme'; import { Point } from '@renderer/types/graphics'; import { CanvasEditor } from '../CanvasEditor'; +import { EventEmitter } from '../common/EventEmitter'; import { MyMouseEvent } from '../common/MouseEventEmitter'; import { StateMachine } from '../data/StateMachine'; import { picto } from '../drawable/Picto'; @@ -16,7 +17,7 @@ export const MIN_SCALE = 0.2; * Контейнер с машиной состояний, в котором происходит отрисовка, * управление камерой, обработка событий и сериализация. */ -export class Container { +export class Container extends EventEmitter { app!: CanvasEditor; isDirty = true; @@ -28,10 +29,9 @@ export class Container { isPan = false; - dropCallback?: (position: Point) => void; - contextMenuOpenCallback?: (position: Point) => void; - constructor(app: CanvasEditor) { + super(); + this.app = app; this.machine = new StateMachine(this); this.states = new States(this); @@ -81,8 +81,9 @@ export class Container { } private initEvents() { - this.app.canvas.element.addEventListener('dragover', (e) => e.preventDefault()); - this.app.canvas.element.addEventListener('drop', this.handleDrop); + // ! Это на будущее + // this.app.canvas.element.addEventListener('dragover', (e) => e.preventDefault()); + // this.app.canvas.element.addEventListener('drop', this.handleDrop); this.app.keyboard.on('spacedown', this.handleSpaceDown); this.app.keyboard.on('spaceup', this.handleSpaceUp); @@ -109,27 +110,24 @@ export class Container { this.isDirty = true; } - handleDrop = (e: DragEvent) => { - e.preventDefault(); + // ! Это на будущее + // handleDrop = (e: DragEvent) => { + // e.preventDefault(); - const rect = this.app.canvas.element.getBoundingClientRect(); - const scale = this.app.manager.data.scale; - const offset = this.app.manager.data.offset; - const position = { - x: (e.clientX - rect.left) * scale - offset.x, - y: (e.clientY - rect.top) * scale - offset.y, - }; + // const rect = this.app.canvas.element.getBoundingClientRect(); + // const scale = this.app.manager.data.scale; + // const offset = this.app.manager.data.offset; + // const position = { + // x: (e.clientX - rect.left) * scale - offset.x, + // y: (e.clientY - rect.top) * scale - offset.y, + // }; - this.dropCallback?.(position); - }; + // this.dropCallback?.(position); + // }; - onStateDrop = (callback: (position: Point) => void) => { - this.dropCallback = callback; - }; - - onFieldContextMenu = (callback: (position: Point) => void) => { - this.contextMenuOpenCallback = callback; - }; + // onStateDrop = (callback: (position: Point) => void) => { + // this.dropCallback = callback; + // }; handleMouseDown = (e: MyMouseEvent) => { this.isPan = true; @@ -171,10 +169,6 @@ export class Container { this.isDirty = true; }; - handleFieldContextMenu = (e: MyMouseEvent) => { - this.contextMenuOpenCallback?.(e); - }; - handleSpaceDown = () => { this.isPan = true; @@ -203,7 +197,11 @@ export class Container { handleMouseDoubleClick = (e: MyMouseEvent) => { e.stopPropagation(); - this.dropCallback?.(this.relativeMousePos({ x: e.x, y: e.y })); + this.emit('dblclick', this.relativeMousePos({ x: e.x, y: e.y })); + }; + + handleFieldContextMenu = (e: MyMouseEvent) => { + this.emit('contextmenu', e); }; relativeMousePos(e: Point): Point { diff --git a/src/renderer/src/lib/data/StateMachine.ts b/src/renderer/src/lib/data/StateMachine.ts index a1be0da9d..0adc59d0a 100644 --- a/src/renderer/src/lib/data/StateMachine.ts +++ b/src/renderer/src/lib/data/StateMachine.ts @@ -157,10 +157,6 @@ export class StateMachine extends EventEmitter { if (parentId) { this.linkState(parentId, newStateId, canUndo); numberOfConnectedActions += 1; - } else { - if (linkByPoint) { - this.linkStateByPoint(state, position); - } } this.container.states.watchState(state); @@ -280,39 +276,6 @@ export class StateMachine extends EventEmitter { this.container.isDirty = true; } - linkStateByPoint(state: State, position: Point) { - // назначаем родительское состояние по месту его создания - let possibleParent: State | undefined = undefined; - for (const item of this.states.values()) { - if (state.id == item.id) continue; - if (item.isUnderMouse(position, true)) { - if (typeof possibleParent === 'undefined') { - possibleParent = item; - } else { - // учитываем вложенность, нужно поместить состояние - // в максимально дочернее - let searchPending = true; - while (searchPending) { - searchPending = false; - for (const child of possibleParent.children.values()) { - if (!(child instanceof State)) continue; - if (state.id == child.id) continue; - if (child.isUnderMouse(position, true)) { - possibleParent = child as State; - searchPending = true; - break; - } - } - } - } - } - } - - if (possibleParent !== state && possibleParent) { - this.linkState(possibleParent.id, state.id, true, true); - } - } - unlinkState(id: string, canUndo = true) { const state = this.states.get(id); if (!state || !state.parent) return; From 01fcd7401237523676f3891ffa7541b73403f690 Mon Sep 17 00:00:00 2001 From: bryzZz Date: Tue, 10 Oct 2023 18:15:25 +0800 Subject: [PATCH 05/10] fix typecheck --- src/renderer/src/lib/data/StateMachine.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/lib/data/StateMachine.ts b/src/renderer/src/lib/data/StateMachine.ts index 0adc59d0a..c1dd05afe 100644 --- a/src/renderer/src/lib/data/StateMachine.ts +++ b/src/renderer/src/lib/data/StateMachine.ts @@ -142,7 +142,7 @@ export class StateMachine extends EventEmitter { } createState = (args: CreateStateParameters, canUndo = true) => { - const { parentId, position, linkByPoint = true } = args; + const { parentId } = args; // Создание данных const newStateId = this.container.app.manager.createState(args); From bee6b4aafb9c5a6a42c753ff85b6f1a5d3b386bf Mon Sep 17 00:00:00 2001 From: bryzZz Date: Fri, 13 Oct 2023 14:29:39 +0800 Subject: [PATCH 06/10] return link by point --- src/renderer/src/lib/data/StateMachine.ts | 37 ++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/lib/data/StateMachine.ts b/src/renderer/src/lib/data/StateMachine.ts index 62e3d71ef..44dea8a29 100644 --- a/src/renderer/src/lib/data/StateMachine.ts +++ b/src/renderer/src/lib/data/StateMachine.ts @@ -141,7 +141,7 @@ export class StateMachine { } createState = (args: CreateStateParameters, canUndo = true) => { - const { parentId } = args; + const { parentId, position, linkByPoint = true } = args; // Создание данных const newStateId = this.container.app.manager.createState(args); @@ -156,6 +156,8 @@ export class StateMachine { if (parentId) { this.linkState(parentId, newStateId, canUndo); numberOfConnectedActions += 1; + } else if (linkByPoint) { + this.linkStateByPoint(state, position); } this.container.states.watchState(state); @@ -278,6 +280,39 @@ export class StateMachine { this.container.isDirty = true; } + linkStateByPoint(state: State, position: Point) { + // назначаем родительское состояние по месту его создания + let possibleParent: State | undefined = undefined; + for (const item of this.states.values()) { + if (state.id == item.id) continue; + if (item.isUnderMouse(position, true)) { + if (typeof possibleParent === 'undefined') { + possibleParent = item; + } else { + // учитываем вложенность, нужно поместить состояние + // в максимально дочернее + let searchPending = true; + while (searchPending) { + searchPending = false; + for (const child of possibleParent.children.values()) { + if (!(child instanceof State)) continue; + if (state.id == child.id) continue; + if (child.isUnderMouse(position, true)) { + possibleParent = child as State; + searchPending = true; + break; + } + } + } + } + } + } + + if (possibleParent !== state && possibleParent) { + this.linkState(possibleParent.id, state.id, true, true); + } + } + unlinkState(id: string, canUndo = true) { const state = this.states.get(id); if (!state || !state.parent) return; From 9c37610f15c71fd459710e63402c31df8fe6c1df Mon Sep 17 00:00:00 2001 From: bryzZz Date: Fri, 13 Oct 2023 14:34:30 +0800 Subject: [PATCH 07/10] return longpress unlik --- src/renderer/src/lib/drawable/States.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/renderer/src/lib/drawable/States.ts b/src/renderer/src/lib/drawable/States.ts index dda914e37..b34075eaa 100644 --- a/src/renderer/src/lib/drawable/States.ts +++ b/src/renderer/src/lib/drawable/States.ts @@ -161,6 +161,15 @@ export class States extends EventEmitter { this.container.machine.changeStatePosition(state.id, e.dragStartPosition, e.dragEndPosition); }; + // если состояние вложено – отсоединяем + handleLongPress = (state: State, e: { event: MyMouseEvent }) => { + e.event.stopPropagation(); + + if (typeof state.parent === 'undefined') return; + + this.container.machine.unlinkState(state.id); + }; + watchState(state: State) { state.on('mouseup', this.handleMouseUpOnState.bind(this, state)); state.on('click', this.handleStateClick.bind(this, state)); @@ -168,6 +177,7 @@ export class States extends EventEmitter { state.on('contextmenu', this.handleContextMenu.bind(this, state)); state.on('drag', this.handleDrag.bind(this, state)); state.on('dragend', this.handleDragEnd.bind(this, state)); + state.on('longpress', this.handleLongPress.bind(this, state)); state.edgeHandlers.onStartNewTransition = this.handleStartNewTransition; } @@ -179,6 +189,7 @@ export class States extends EventEmitter { state.off('contextmenu', this.handleContextMenu.bind(this, state)); state.off('drag', this.handleDrag.bind(this, state)); state.off('dragend', this.handleDragEnd.bind(this, state)); + state.off('longpress', this.handleLongPress.bind(this, state)); state.edgeHandlers.unbindEvents(); state.unbindEvents(); From 98901cff894223de11bd6684c2efeb60863d46f9 Mon Sep 17 00:00:00 2001 From: bryzZz Date: Thu, 19 Oct 2023 19:21:26 +0800 Subject: [PATCH 08/10] add drag throttling --- package-lock.json | 22 ++++++++++++++++++++++ package.json | 2 ++ src/renderer/src/lib/drawable/States.ts | 6 ++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 042616dde..10193f2ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "electron-settings": "^4.0.2", "find-free-port": "^2.0.0", "isomorphic-ws": "^5.0.0", + "lodash.throttle": "^4.1.1", "monaco-editor": "^0.39.0", "monaco-editor-webpack-plugin": "^7.1.0", "nanoid": "^4.0.2", @@ -41,6 +42,7 @@ "devDependencies": { "@electron-toolkit/tsconfig": "^1.0.1", "@electron/notarize": "^1.2.3", + "@types/lodash.throttle": "^4.1.8", "@types/node": "^18.16.16", "@types/react": "^18.2.8", "@types/react-document-title": "^2.0.5", @@ -1862,6 +1864,21 @@ "@types/node": "*" } }, + "node_modules/@types/lodash": { + "version": "4.14.200", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz", + "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==", + "dev": true + }, + "node_modules/@types/lodash.throttle": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/lodash.throttle/-/lodash.throttle-4.1.8.tgz", + "integrity": "sha512-EJT8Wg9HLcrsaTlFJ+wmolrGMCC/WBmqOISNi1y9hukgp15cYnfO435X1ReUl0VTIAYnRailHqSZEmzLJb5fiQ==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", @@ -7235,6 +7252,11 @@ "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" + }, "node_modules/lodash.unset": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/lodash.unset/-/lodash.unset-4.5.2.tgz", diff --git a/package.json b/package.json index 0297ca677..93452144b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "electron-settings": "^4.0.2", "find-free-port": "^2.0.0", "isomorphic-ws": "^5.0.0", + "lodash.throttle": "^4.1.1", "monaco-editor": "^0.39.0", "monaco-editor-webpack-plugin": "^7.1.0", "nanoid": "^4.0.2", @@ -61,6 +62,7 @@ "devDependencies": { "@electron-toolkit/tsconfig": "^1.0.1", "@electron/notarize": "^1.2.3", + "@types/lodash.throttle": "^4.1.8", "@types/node": "^18.16.16", "@types/react": "^18.2.8", "@types/react-document-title": "^2.0.5", diff --git a/src/renderer/src/lib/drawable/States.ts b/src/renderer/src/lib/drawable/States.ts index b34075eaa..b048d2356 100644 --- a/src/renderer/src/lib/drawable/States.ts +++ b/src/renderer/src/lib/drawable/States.ts @@ -1,3 +1,5 @@ +import throttle from 'lodash.throttle'; + import { Point } from '@renderer/types/graphics'; import { EventSelection } from './Events'; @@ -107,7 +109,7 @@ export class States extends EventEmitter { } }; - handleDrag = (state: State, e: { event: MyMouseEvent }) => { + handleDrag: (state: State, e: { event: MyMouseEvent }) => void = throttle((state, e) => { const position = { x: e.event.x, y: e.event.y }; // Чтобы проверять начиная со своего уровня вложенности @@ -149,7 +151,7 @@ export class States extends EventEmitter { childId: state.id, }; } - }; + }, 100); handleDragEnd = (state: State, e: { dragStartPosition: Point; dragEndPosition: Point }) => { if (this.dragInfo) { From dcc877afc44a6faf9b26f414571ee2bd131bbc4c Mon Sep 17 00:00:00 2001 From: bryzZz Date: Sun, 5 Nov 2023 16:55:10 +0800 Subject: [PATCH 09/10] fix --- src/renderer/src/lib/data/StatesController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/lib/data/StatesController.ts b/src/renderer/src/lib/data/StatesController.ts index 34f5f0810..413a109e3 100644 --- a/src/renderer/src/lib/data/StatesController.ts +++ b/src/renderer/src/lib/data/StatesController.ts @@ -104,7 +104,7 @@ export class StatesController extends EventEmitter { const possibleParent = (state.parent ?? this.container).getCapturedNode({ position: e.event, exclude: [state.id], - includeChildrenHeight: true, + includeChildrenHeight: false, type: 'states', }); From c8119cb38540a6b925577b3363cf1e8ff88082ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=A2=D0=B5=D0=B1?= =?UTF-8?q?=D0=BB=D0=BE=D0=B5=D0=B2?= Date: Sat, 11 Nov 2023 18:49:05 +0800 Subject: [PATCH 10/10] Update Container.ts --- src/renderer/src/lib/basic/Container.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/renderer/src/lib/basic/Container.ts b/src/renderer/src/lib/basic/Container.ts index fd1e16aa3..45b57d350 100644 --- a/src/renderer/src/lib/basic/Container.ts +++ b/src/renderer/src/lib/basic/Container.ts @@ -61,8 +61,6 @@ export class Container extends EventEmitter { draw(ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement) { this.drawGrid(ctx, canvas); - console.log(this.children); - const drawChildren = (node: Container | Node) => { node.children.forEach((child) => { child.draw(ctx, canvas);