Skip to content

Commit

Permalink
add evens undoRedo
Browse files Browse the repository at this point in the history
  • Loading branch information
bryzZz committed Oct 1, 2023
1 parent cad426b commit df7f46f
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 80 deletions.
12 changes: 4 additions & 8 deletions src/renderer/src/components/DiagramEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const DiagramEditor: React.FC<DiagramEditorProps> = ({ manager, editor, s
// manager.triggerDataUpdate();
});

editor.container.states.onStateEventCreate((state, event, click) => {
editor.container.states.onStateEventChange((state, event, click) => {
ClearUseState();
setIdEvents({ state, event, click });
openEventsModal();
Expand Down Expand Up @@ -113,12 +113,8 @@ export const DiagramEditor: React.FC<DiagramEditorProps> = ({ manager, editor, s

const handleCreateEventsModal = (data: EventsModalResult) => {
setEvents([...events, data.action]);
if (!isModalOpen) {
editor?.container.machine.createOrChangeEvent(
data.id?.state.id,
data.id?.event,
data.trigger
);
if (!isModalOpen && data.id?.event) {
editor?.container.machine.changeEvent(data.id?.state.id, data.id.event, data.trigger);
}
closeEventsModal();
};
Expand All @@ -129,7 +125,7 @@ export const DiagramEditor: React.FC<DiagramEditorProps> = ({ manager, editor, s
id: data.id,
triggerComponent: data.trigger.component,
triggerMethod: data.trigger.method,
events,
actions: events,
});
} else if (transition && data.key === 3) {
editor?.container.machine.changeTransition({
Expand Down
5 changes: 2 additions & 3 deletions src/renderer/src/hooks/useDiagramContextMenu.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useEffect, useState } from 'react';

import { useTabs } from '@renderer/store/useTabs';

import { CanvasEditor } from '@renderer/lib/CanvasEditor';
import { EditorManager } from '@renderer/lib/data/EditorManager';
import { Condition } from '@renderer/lib/drawable/Condition';
import { State } from '@renderer/lib/drawable/State';
import { useTabs } from '@renderer/store/useTabs';
import { Point } from '@renderer/types/graphics';

type DiagramContextMenuItem = { label: string; action: () => void };
Expand Down Expand Up @@ -133,7 +132,7 @@ export const useDiagramContextMenu = (editor: CanvasEditor | null, manager: Edit
{
label: 'Удалить',
action: () => {
editor?.container.machine.deleteEvent(state.id as string, event);
editor?.container.machine.deleteEvent(state.id, event);
},
},
]);
Expand Down
112 changes: 77 additions & 35 deletions src/renderer/src/lib/data/EditorManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
Transition,
Component,
Elements,
EventData,
} from '@renderer/types/diagram';
import {
emptyEditorData,
Expand All @@ -32,6 +33,7 @@ import { Point, Rectangle } from '@renderer/types/graphics';
import { isPlatformAvailable } from './PlatformLoader';

import ElementsJSONCodec from '../codecs/ElementsJSONCodec';
import { EventSelection } from '../drawable/Events';
import { stateStyle } from '../styles';

export type FileError = {
Expand Down Expand Up @@ -343,31 +345,36 @@ export class EditorManager {
return newId;
}

changeStateEvents({ id, triggerComponent, triggerMethod, events }: ChangeStateEventsParams) {
changeStateEvents({ id, triggerComponent, triggerMethod, actions }: ChangeStateEventsParams) {
const state = this.data.elements.states[id];
if (!state) return false;

const trueTab = state.events.find(
const eventIndex = state.events.findIndex(
(value) =>
triggerComponent === value.trigger.component &&
triggerMethod === value.trigger.method &&
undefined === value.trigger.args // FIXME: сравнение по args может не работать
);
const event = state.events[eventIndex];

if (trueTab === undefined) {
if (event === undefined) {
state.events = [
...state.events,
{
do: events,
do: actions,
trigger: {
component: triggerComponent,
method: triggerMethod,
//args: {},
// args: {},
},
},
];
} else {
trueTab.do = [...events];
if (actions.length) {
event.do = [...actions];
} else {
state.events.splice(eventIndex, 1);
}
}

return true;
Expand Down Expand Up @@ -447,46 +454,81 @@ export class EditorManager {
return true;
}

changeEvent(stateId: string, event: any, newValue: Event | Action) {
createEvent(stateId: string, eventData: EventData) {
const state = this.data.elements.states[stateId];
if (!state) return false;

//Проверяем по условию, что мы редактируем, либо главное событие, либо действие
if (event.actionIdx === null) {
const trueTab = state.events.find(
(value, id) =>
event.eventIdx !== id &&
newValue.component === value.trigger.component &&
newValue.method === value.trigger.method &&
undefined === value.trigger.args // FIXME: сравнение по args может не работать
);
state.events.push(eventData);

if (trueTab === undefined) {
state.events[event.eventIdx].trigger = newValue;
} else {
trueTab.do = [...trueTab.do, ...state.events[event.eventIdx].do];
state.events.splice(event.eventIdx, 1);
}
} else {
state.events[event.eventIdx].do[event.actionIdx] = newValue;
}
return true;
}

createEventAction(stateId: string, event: EventSelection, value: Action) {
const state = this.data.elements.states[stateId];
if (!state) return false;

const { eventIdx, actionIdx } = event;

state.events[eventIdx].do.splice(actionIdx ?? state.events[eventIdx].do.length - 1, 0, value);

return true;
}

deleteEvent(stateId: string, eventIdx: number, actionIdx: number | null) {
changeEvent(stateId: string, eventIdx: number, newValue: Event) {
const state = this.data.elements.states[stateId];
if (!state) return false;

if (actionIdx !== null) {
state.events[eventIdx].do.splice(actionIdx!, 1);
// Проверяем, есть ли действия в событие, если нет, то удалять его
if (state.events[eventIdx].do.length === 0) {
state.events.splice(eventIdx, 1);
}
} else {
state.events.splice(eventIdx, 1);
}
// const event = state.events.find(
// (value, id) =>
// eventIdx !== id &&
// newValue.component === value.trigger.component &&
// newValue.method === value.trigger.method &&
// undefined === value.trigger.args // FIXME: сравнение по args может не работать
// );

const event = state.events[eventIdx];

if (!event) return false;

event.trigger = newValue;

// if (trueTab === undefined) {
// state.events[eventIdx].trigger = newValue;
// } else {
// event.do = [...event.do, ...state.events[eventIdx].do];
// state.events.splice(eventIdx, 1);
// }

return true;
}

changeEventAction(stateId: string, event: EventSelection, newValue: Action) {
const state = this.data.elements.states[stateId];
if (!state) return false;

const { eventIdx, actionIdx } = event;

state.events[eventIdx].do[actionIdx as number] = newValue;

return true;
}

deleteEvent(stateId: string, eventIdx: number) {
const state = this.data.elements.states[stateId];
if (!state) return false;

state.events.splice(eventIdx, 1);

return true;
}

deleteEventAction(stateId: string, event: EventSelection) {
const state = this.data.elements.states[stateId];
if (!state) return false;

const { eventIdx, actionIdx } = event;

state.events[eventIdx].do.splice(actionIdx as number, 1);

return true;
}
Expand Down
108 changes: 93 additions & 15 deletions src/renderer/src/lib/data/StateMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Variable,
State as StateType,
Transition as TransitionType,
EventData,
} from '@renderer/types/diagram';
import {
AddComponentParams,
Expand Down Expand Up @@ -173,9 +174,18 @@ export class StateMachine extends EventEmitter {
if (!state) return;

if (canUndo) {
const prevEvent = state.data.events.find(
(value) =>
args.triggerComponent === value.trigger.component &&
args.triggerMethod === value.trigger.method &&
undefined === value.trigger.args // FIXME: сравнение по args может не работать
);

const prevActions = structuredClone(prevEvent?.do ?? []);

this.undoRedo.do({
type: 'changeStateEvents',
args: { state, args },
args: { args, prevActions },
});
}

Expand All @@ -186,7 +196,7 @@ export class StateMachine extends EventEmitter {
this.container.isDirty = true;
}

setStateEvents(args: SetStateEventsParams) {
setStateEvents(args: SetStateEventsParams, canUndo = true) {

Check failure on line 199 in src/renderer/src/lib/data/StateMachine.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'canUndo' is declared but its value is never read.
const { id } = args;

const state = this.states.get(id);
Expand Down Expand Up @@ -490,12 +500,12 @@ export class StateMachine extends EventEmitter {
this.states.forEach((state) => {
if (state.isSelected) {
if (state.eventBox.selection) {
this.deleteEvent(state.id!, state.eventBox.selection);
this.deleteEvent(state.id, state.eventBox.selection);
state.eventBox.selection = undefined;
removed = true;
return;
} else {
killList.push(state.id!);
killList.push(state.id);
}
}
});
Expand Down Expand Up @@ -570,19 +580,58 @@ export class StateMachine extends EventEmitter {
this.container.isDirty = true;
}

createEvent(stateId: string, eventData: EventData, canUndo = true) {

Check failure on line 583 in src/renderer/src/lib/data/StateMachine.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'canUndo' is declared but its value is never read.
const state = this.states.get(stateId);
if (!state) return;

this.container.app.manager.createEvent(stateId, eventData);

state.eventBox.recalculate();

this.container.isDirty = true;
}

createEventAction(stateId: string, event: EventSelection, value: Action, canUndo = true) {

Check failure on line 594 in src/renderer/src/lib/data/StateMachine.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'canUndo' is declared but its value is never read.
const state = this.states.get(stateId);
if (!state) return;

this.container.app.manager.createEventAction(stateId, event, value);

state.eventBox.recalculate();

this.container.isDirty = true;
}

// Редактирование события в состояниях
createOrChangeEvent(stateId: string, event: any, newValue: Event | Action, canUndo = true) {
changeEvent(stateId: string, event: EventSelection, newValue: Event | Action, canUndo = true) {
const state = this.states.get(stateId);
if (!state) return;

if (canUndo) {
this.undoRedo.do({
type: 'changeEvent',
args: { stateId, event, newValue },
});
}
const { eventIdx, actionIdx } = event;

if (actionIdx !== null) {
const prevValue = state.data.events[eventIdx].do[actionIdx];

this.container.app.manager.changeEvent(stateId, event, newValue);
this.container.app.manager.changeEventAction(stateId, event, newValue);

if (canUndo) {
this.undoRedo.do({
type: 'changeEvent',
args: { stateId, event, newValue, prevValue },
});
}
} else {
const prevValue = state.data.events[eventIdx].trigger;

this.container.app.manager.changeEvent(stateId, eventIdx, newValue);

if (canUndo) {
this.undoRedo.do({
type: 'changeEvent',
args: { stateId, event, newValue, prevValue },
});
}
}

state.eventBox.recalculate();

Expand All @@ -591,11 +640,40 @@ export class StateMachine extends EventEmitter {

// Удаление события в состояниях
//TODO показывать предупреждение при удалении события в состоянии(модалка)
deleteEvent(id: string, eventId: EventSelection) {
const state = this.states.get(id);
deleteEvent(stateId: string, event: EventSelection, canUndo = true) {
const state = this.states.get(stateId);
if (!state) return;

this.container.app.manager.deleteEvent(id, eventId.eventIdx, eventId.actionIdx);
const { eventIdx, actionIdx } = event;

if (actionIdx !== null) {
// Проверяем если действие в событие последнее то надо удалить всё событие
if (state.data.events[eventIdx].do.length === 1) {
return this.deleteEvent(stateId, { eventIdx, actionIdx: null });
}

const prevValue = state.data.events[eventIdx].do[actionIdx];

this.container.app.manager.deleteEventAction(stateId, event);

if (canUndo) {
this.undoRedo.do({
type: 'deleteEventAction',
args: { stateId, event, prevValue },
});
}
} else {
const prevValue = state.data.events[eventIdx];

this.container.app.manager.deleteEvent(stateId, eventIdx);

if (canUndo) {
this.undoRedo.do({
type: 'deleteEvent',
args: { stateId, eventIdx, prevValue },
});
}
}

this.container.isDirty = true;
}
Expand Down
Loading

0 comments on commit df7f46f

Please sign in to comment.