@finos/legend-extension-dsl-diagram 8.1.195 → 8.1.197
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/DiagramRenderer.d.ts +39 -2
- package/lib/components/DiagramRenderer.d.ts.map +1 -1
- package/lib/components/DiagramRenderer.js +83 -61
- package/lib/components/DiagramRenderer.js.map +1 -1
- package/lib/components/DiagramViewer.d.ts +39 -0
- package/lib/components/DiagramViewer.d.ts.map +1 -0
- package/lib/components/DiagramViewer.js +170 -0
- package/lib/components/DiagramViewer.js.map +1 -0
- package/lib/components/DiagramViewerState.d.ts +44 -0
- package/lib/components/DiagramViewerState.d.ts.map +1 -0
- package/lib/components/DiagramViewerState.js +136 -0
- package/lib/components/DiagramViewerState.js.map +1 -0
- package/lib/components/index.d.ts +4 -1
- package/lib/components/index.d.ts.map +1 -1
- package/lib/components/index.js +4 -1
- package/lib/components/index.js.map +1 -1
- package/lib/graph-manager/index.d.ts +3 -0
- package/lib/graph-manager/index.d.ts.map +1 -1
- package/lib/graph-manager/index.js +3 -0
- package/lib/graph-manager/index.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/package.json +4 -5
- package/package.json +8 -9
- package/src/components/DiagramRenderer.ts +221 -103
- package/src/components/DiagramViewer.tsx +650 -0
- package/src/components/DiagramViewerState.ts +171 -0
- package/src/components/index.ts +4 -0
- package/src/graph-manager/index.ts +3 -0
- package/src/index.ts +0 -1
- package/tsconfig.json +2 -12
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioApplicationNavigationContext.d.ts +0 -19
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioApplicationNavigationContext.d.ts.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioApplicationNavigationContext.js +0 -20
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioApplicationNavigationContext.js.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioCodeSnippet.d.ts +0 -20
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioCodeSnippet.d.ts.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioCodeSnippet.js +0 -81
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioCodeSnippet.js.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioCommand.d.ts +0 -28
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioCommand.d.ts.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioCommand.js +0 -62
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioCommand.js.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioDocumentation.d.ts +0 -20
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioDocumentation.d.ts.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioDocumentation.js +0 -21
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioDocumentation.js.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioTesting.d.ts +0 -20
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioTesting.d.ts.map +0 -1
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioTesting.js +0 -21
- package/lib/__lib__/studio/DSL_Diagram_LegendStudioTesting.js.map +0 -1
- package/lib/components/studio/ClassDiagramPreview.d.ts +0 -22
- package/lib/components/studio/ClassDiagramPreview.d.ts.map +0 -1
- package/lib/components/studio/ClassDiagramPreview.js +0 -64
- package/lib/components/studio/ClassDiagramPreview.js.map +0 -1
- package/lib/components/studio/DSL_Diagram_LegendStudioApplicationPlugin.d.ts +0 -42
- package/lib/components/studio/DSL_Diagram_LegendStudioApplicationPlugin.d.ts.map +0 -1
- package/lib/components/studio/DSL_Diagram_LegendStudioApplicationPlugin.js +0 -216
- package/lib/components/studio/DSL_Diagram_LegendStudioApplicationPlugin.js.map +0 -1
- package/lib/components/studio/DiagramEditor.d.ts +0 -19
- package/lib/components/studio/DiagramEditor.d.ts.map +0 -1
- package/lib/components/studio/DiagramEditor.js +0 -436
- package/lib/components/studio/DiagramEditor.js.map +0 -1
- package/lib/components/studio/InheritanceDiagramRenderer.d.ts +0 -22
- package/lib/components/studio/InheritanceDiagramRenderer.d.ts.map +0 -1
- package/lib/components/studio/InheritanceDiagramRenderer.js +0 -34
- package/lib/components/studio/InheritanceDiagramRenderer.js.map +0 -1
- package/lib/components/studio/index.d.ts +0 -18
- package/lib/components/studio/index.d.ts.map +0 -1
- package/lib/components/studio/index.js +0 -18
- package/lib/components/studio/index.js.map +0 -1
- package/lib/stores/studio/DSL_Diagram_GraphModifierHelper.d.ts +0 -57
- package/lib/stores/studio/DSL_Diagram_GraphModifierHelper.d.ts.map +0 -1
- package/lib/stores/studio/DSL_Diagram_GraphModifierHelper.js +0 -94
- package/lib/stores/studio/DSL_Diagram_GraphModifierHelper.js.map +0 -1
- package/lib/stores/studio/DiagramEditorState.d.ts +0 -88
- package/lib/stores/studio/DiagramEditorState.d.ts.map +0 -1
- package/lib/stores/studio/DiagramEditorState.js +0 -341
- package/lib/stores/studio/DiagramEditorState.js.map +0 -1
- package/src/__lib__/studio/DSL_Diagram_LegendStudioApplicationNavigationContext.ts +0 -19
- package/src/__lib__/studio/DSL_Diagram_LegendStudioCodeSnippet.ts +0 -88
- package/src/__lib__/studio/DSL_Diagram_LegendStudioCommand.ts +0 -64
- package/src/__lib__/studio/DSL_Diagram_LegendStudioDocumentation.ts +0 -20
- package/src/__lib__/studio/DSL_Diagram_LegendStudioTesting.ts +0 -20
- package/src/components/studio/ClassDiagramPreview.tsx +0 -83
- package/src/components/studio/DSL_Diagram_LegendStudioApplicationPlugin.tsx +0 -313
- package/src/components/studio/DiagramEditor.tsx +0 -1514
- package/src/components/studio/InheritanceDiagramRenderer.ts +0 -50
- package/src/components/studio/index.ts +0 -19
- package/src/stores/studio/DSL_Diagram_GraphModifierHelper.ts +0 -166
- package/src/stores/studio/DiagramEditorState.ts +0 -487
|
@@ -1,1514 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2020-present, Goldman Sachs
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { useRef, useState, useEffect, useCallback, forwardRef } from 'react';
|
|
18
|
-
import { type DropTargetMonitor, useDrop } from 'react-dnd';
|
|
19
|
-
import { observer } from 'mobx-react-lite';
|
|
20
|
-
import {
|
|
21
|
-
DIAGRAM_ALIGNER_OPERATOR,
|
|
22
|
-
DiagramRenderer,
|
|
23
|
-
DIAGRAM_INTERACTION_MODE,
|
|
24
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE,
|
|
25
|
-
DIAGRAM_ZOOM_LEVELS,
|
|
26
|
-
} from '../DiagramRenderer.js';
|
|
27
|
-
import {
|
|
28
|
-
type DiagramEditorInlineClassCreatorState,
|
|
29
|
-
type DiagramEditorInlineClassRenamerState,
|
|
30
|
-
type DiagramEditorInlinePropertyEditorState,
|
|
31
|
-
DIAGRAM_EDITOR_SIDE_PANEL_TAB,
|
|
32
|
-
DiagramEditorClassViewEditorSidePanelState,
|
|
33
|
-
DiagramEditorState,
|
|
34
|
-
} from '../../stores/studio/DiagramEditorState.js';
|
|
35
|
-
import {
|
|
36
|
-
type ResizablePanelHandlerProps,
|
|
37
|
-
ContextMenu,
|
|
38
|
-
getCollapsiblePanelGroupProps,
|
|
39
|
-
BasePopover,
|
|
40
|
-
BlankPanelContent,
|
|
41
|
-
CaretDownIcon,
|
|
42
|
-
CheckSquareIcon,
|
|
43
|
-
clsx,
|
|
44
|
-
createFilter,
|
|
45
|
-
CustomSelectorInput,
|
|
46
|
-
KeyboardIcon,
|
|
47
|
-
ControlledDropdownMenu,
|
|
48
|
-
MenuContent,
|
|
49
|
-
MenuContentDivider,
|
|
50
|
-
MenuContentItem,
|
|
51
|
-
PlusIcon,
|
|
52
|
-
SquareIcon,
|
|
53
|
-
ResizablePanelGroup,
|
|
54
|
-
ResizablePanelSplitter,
|
|
55
|
-
ResizablePanel,
|
|
56
|
-
ResizeIcon,
|
|
57
|
-
MinusIcon,
|
|
58
|
-
MousePointerIcon,
|
|
59
|
-
MoveIcon,
|
|
60
|
-
PlusCircleIcon,
|
|
61
|
-
SidebarIcon,
|
|
62
|
-
TriangleIcon,
|
|
63
|
-
ZoomInIcon,
|
|
64
|
-
ZoomOutIcon,
|
|
65
|
-
Dialog,
|
|
66
|
-
AlignEndIcon,
|
|
67
|
-
DistributeHorizontalIcon,
|
|
68
|
-
DistributeVerticalIcon,
|
|
69
|
-
AlignStartIcon,
|
|
70
|
-
AlignCenterIcon,
|
|
71
|
-
AlignTopIcon,
|
|
72
|
-
AlignMiddleIcon,
|
|
73
|
-
AlignBottomIcon,
|
|
74
|
-
useResizeDetector,
|
|
75
|
-
Modal,
|
|
76
|
-
ModalBody,
|
|
77
|
-
ModalHeader,
|
|
78
|
-
} from '@finos/legend-art';
|
|
79
|
-
import {
|
|
80
|
-
type Type,
|
|
81
|
-
type Multiplicity,
|
|
82
|
-
Class,
|
|
83
|
-
DerivedProperty,
|
|
84
|
-
Property,
|
|
85
|
-
ELEMENT_PATH_DELIMITER,
|
|
86
|
-
MULTIPLICITY_INFINITE,
|
|
87
|
-
GenericType,
|
|
88
|
-
createPath,
|
|
89
|
-
isValidFullPath,
|
|
90
|
-
isValidPathIdentifier,
|
|
91
|
-
resolvePackagePathAndElementName,
|
|
92
|
-
} from '@finos/legend-graph';
|
|
93
|
-
import { guaranteeNonNullable, prettyCONSTName } from '@finos/legend-shared';
|
|
94
|
-
import { flowResult } from 'mobx';
|
|
95
|
-
import {
|
|
96
|
-
useApplicationStore,
|
|
97
|
-
useApplicationNavigationContext,
|
|
98
|
-
useCommands,
|
|
99
|
-
} from '@finos/legend-application';
|
|
100
|
-
import {
|
|
101
|
-
ClassFormEditor,
|
|
102
|
-
CORE_DND_TYPE,
|
|
103
|
-
ElementDragSource,
|
|
104
|
-
useEditorStore,
|
|
105
|
-
property_setName,
|
|
106
|
-
property_setGenericType,
|
|
107
|
-
property_setMultiplicity,
|
|
108
|
-
queryClass,
|
|
109
|
-
} from '@finos/legend-application-studio';
|
|
110
|
-
import { cleanUpDeadReferencesInDiagram } from '../../graph/helpers/DSL_Diagram_Helper.js';
|
|
111
|
-
import { Point } from '../../graph/metamodel/pure/packageableElements/diagram/geometry/DSL_Diagram_Point.js';
|
|
112
|
-
import {
|
|
113
|
-
classView_setHideProperties,
|
|
114
|
-
classView_setHideStereotypes,
|
|
115
|
-
classView_setHideTaggedValues,
|
|
116
|
-
} from '../../stores/studio/DSL_Diagram_GraphModifierHelper.js';
|
|
117
|
-
import { DSL_DIAGRAM_LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../__lib__/studio/DSL_Diagram_LegendStudioApplicationNavigationContext.js';
|
|
118
|
-
import { DSL_DIAGRAM_TEST_ID } from '../../__lib__/studio/DSL_Diagram_LegendStudioTesting.js';
|
|
119
|
-
import {
|
|
120
|
-
buildElementOption,
|
|
121
|
-
type PackageableElementOption,
|
|
122
|
-
} from '@finos/legend-lego/graph-editor';
|
|
123
|
-
|
|
124
|
-
const DiagramEditorContextMenu = observer(
|
|
125
|
-
forwardRef<
|
|
126
|
-
HTMLDivElement,
|
|
127
|
-
{
|
|
128
|
-
diagramEditorState: DiagramEditorState;
|
|
129
|
-
}
|
|
130
|
-
>(function DiagramEditorContextMenu(props, ref) {
|
|
131
|
-
const { diagramEditorState } = props;
|
|
132
|
-
const editorStore = useEditorStore();
|
|
133
|
-
|
|
134
|
-
// actions
|
|
135
|
-
const buildQuery = editorStore.applicationStore.guardUnhandledError(
|
|
136
|
-
async () => {
|
|
137
|
-
const classView = guaranteeNonNullable(
|
|
138
|
-
diagramEditorState.contextMenuClassView,
|
|
139
|
-
);
|
|
140
|
-
await queryClass(classView.class.value, editorStore);
|
|
141
|
-
},
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
return (
|
|
145
|
-
<MenuContent>
|
|
146
|
-
<MenuContentItem onClick={buildQuery}>Query...</MenuContentItem>
|
|
147
|
-
</MenuContent>
|
|
148
|
-
);
|
|
149
|
-
}),
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
const DiagramRendererHotkeyInfosModal = observer(
|
|
153
|
-
(props: { open: boolean; onClose: () => void }) => {
|
|
154
|
-
const { open, onClose } = props;
|
|
155
|
-
const applicationStore = useApplicationStore();
|
|
156
|
-
return (
|
|
157
|
-
<Dialog
|
|
158
|
-
open={open}
|
|
159
|
-
onClose={onClose}
|
|
160
|
-
classes={{
|
|
161
|
-
root: 'editor-modal__root-container',
|
|
162
|
-
container: 'editor-modal__container',
|
|
163
|
-
paper: 'editor-modal__content--scrollable',
|
|
164
|
-
}}
|
|
165
|
-
>
|
|
166
|
-
<Modal
|
|
167
|
-
darkMode={
|
|
168
|
-
!applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
|
|
169
|
-
}
|
|
170
|
-
className="modal--scrollable diagram-editor__hotkeys__dialog"
|
|
171
|
-
>
|
|
172
|
-
<ModalHeader title="Diagram Hotkeys" />
|
|
173
|
-
<ModalBody>
|
|
174
|
-
<div className="diagram-editor__hotkey__groups">
|
|
175
|
-
<div className="diagram-editor__hotkey__group">
|
|
176
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
177
|
-
Use view tool
|
|
178
|
-
</div>
|
|
179
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
180
|
-
<div className="hotkey__key">V</div>
|
|
181
|
-
</div>
|
|
182
|
-
</div>
|
|
183
|
-
<div className="diagram-editor__hotkey__group">
|
|
184
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
185
|
-
Use pan tool
|
|
186
|
-
</div>
|
|
187
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
188
|
-
<div className="hotkey__key">M</div>
|
|
189
|
-
</div>
|
|
190
|
-
</div>
|
|
191
|
-
<div className="diagram-editor__hotkey__group">
|
|
192
|
-
<div className="diagram-editor__hotkey__annotation">Zoom</div>
|
|
193
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
194
|
-
<div className="hotkey__key">Z</div>
|
|
195
|
-
</div>
|
|
196
|
-
</div>
|
|
197
|
-
<div className="diagram-editor__hotkey__group">
|
|
198
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
199
|
-
Recenter
|
|
200
|
-
</div>
|
|
201
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
202
|
-
<div className="hotkey__key">R</div>
|
|
203
|
-
</div>
|
|
204
|
-
</div>
|
|
205
|
-
|
|
206
|
-
<div className="diagram-editor__hotkey__groups__divider" />
|
|
207
|
-
<div className="diagram-editor__hotkey__group">
|
|
208
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
209
|
-
Remove selected element(s)
|
|
210
|
-
</div>
|
|
211
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
212
|
-
<div className="hotkey__key">Remove</div>
|
|
213
|
-
</div>
|
|
214
|
-
</div>
|
|
215
|
-
<div className="diagram-editor__hotkey__group">
|
|
216
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
217
|
-
Edit the selected element
|
|
218
|
-
</div>
|
|
219
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
220
|
-
<div className="hotkey__key">E</div>
|
|
221
|
-
</div>
|
|
222
|
-
</div>
|
|
223
|
-
|
|
224
|
-
<div className="diagram-editor__hotkey__groups__divider" />
|
|
225
|
-
<div className="diagram-editor__hotkey__group">
|
|
226
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
227
|
-
Use property tool
|
|
228
|
-
</div>
|
|
229
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
230
|
-
<div className="hotkey__key">P</div>
|
|
231
|
-
</div>
|
|
232
|
-
</div>
|
|
233
|
-
<div className="diagram-editor__hotkey__group">
|
|
234
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
235
|
-
Use inheritance tool
|
|
236
|
-
</div>
|
|
237
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
238
|
-
<div className="hotkey__key">I</div>
|
|
239
|
-
</div>
|
|
240
|
-
</div>
|
|
241
|
-
<div className="diagram-editor__hotkey__group">
|
|
242
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
243
|
-
Add class
|
|
244
|
-
</div>
|
|
245
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
246
|
-
<div className="hotkey__key">C</div>
|
|
247
|
-
</div>
|
|
248
|
-
</div>
|
|
249
|
-
<div className="diagram-editor__hotkey__group">
|
|
250
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
251
|
-
Add simple property to selected class
|
|
252
|
-
</div>
|
|
253
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
254
|
-
<div className="hotkey__key">Alt</div>
|
|
255
|
-
<div className="hotkey__plus">
|
|
256
|
-
<PlusIcon />
|
|
257
|
-
</div>
|
|
258
|
-
<div className="hotkey__key">↓</div>
|
|
259
|
-
</div>
|
|
260
|
-
</div>
|
|
261
|
-
|
|
262
|
-
<div className="diagram-editor__hotkey__groups__divider" />
|
|
263
|
-
<div className="diagram-editor__hotkey__group">
|
|
264
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
265
|
-
Toggle display for properties of selected classes
|
|
266
|
-
</div>
|
|
267
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
268
|
-
<div className="hotkey__key">Alt</div>
|
|
269
|
-
<div className="hotkey__plus">
|
|
270
|
-
<PlusIcon />
|
|
271
|
-
</div>
|
|
272
|
-
<div className="hotkey__key">P</div>
|
|
273
|
-
</div>
|
|
274
|
-
</div>
|
|
275
|
-
<div className="diagram-editor__hotkey__group">
|
|
276
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
277
|
-
Toggle display for tagged values of selected classes
|
|
278
|
-
</div>
|
|
279
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
280
|
-
<div className="hotkey__key">Alt</div>
|
|
281
|
-
<div className="hotkey__plus">
|
|
282
|
-
<PlusIcon />
|
|
283
|
-
</div>
|
|
284
|
-
<div className="hotkey__key">T</div>
|
|
285
|
-
</div>
|
|
286
|
-
</div>
|
|
287
|
-
<div className="diagram-editor__hotkey__group">
|
|
288
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
289
|
-
Toggle display for stereotypes of selected classes
|
|
290
|
-
</div>
|
|
291
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
292
|
-
<div className="hotkey__key">Alt</div>
|
|
293
|
-
<div className="hotkey__plus">
|
|
294
|
-
<PlusIcon />
|
|
295
|
-
</div>
|
|
296
|
-
<div className="hotkey__key">S</div>
|
|
297
|
-
</div>
|
|
298
|
-
</div>
|
|
299
|
-
|
|
300
|
-
<div className="diagram-editor__hotkey__groups__divider" />
|
|
301
|
-
<div className="diagram-editor__hotkey__group">
|
|
302
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
303
|
-
Eject the property
|
|
304
|
-
</div>
|
|
305
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
306
|
-
<div className="hotkey__key">→</div>
|
|
307
|
-
</div>
|
|
308
|
-
</div>
|
|
309
|
-
<div className="diagram-editor__hotkey__group">
|
|
310
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
311
|
-
Add subtypes of the selected classes to the diagram
|
|
312
|
-
</div>
|
|
313
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
314
|
-
<div className="hotkey__key">↓</div>
|
|
315
|
-
</div>
|
|
316
|
-
</div>
|
|
317
|
-
<div className="diagram-editor__hotkey__group">
|
|
318
|
-
<div className="diagram-editor__hotkey__annotation">
|
|
319
|
-
Add supertypes of the selected classes to the diagram
|
|
320
|
-
</div>
|
|
321
|
-
<div className="hotkey__combination diagram-editor__hotkey__keys">
|
|
322
|
-
<div className="hotkey__key">↑</div>
|
|
323
|
-
</div>
|
|
324
|
-
</div>
|
|
325
|
-
</div>
|
|
326
|
-
</ModalBody>
|
|
327
|
-
</Modal>
|
|
328
|
-
</Dialog>
|
|
329
|
-
);
|
|
330
|
-
},
|
|
331
|
-
);
|
|
332
|
-
|
|
333
|
-
const DiagramEditorToolPanel = observer(
|
|
334
|
-
(props: { diagramEditorState: DiagramEditorState }) => {
|
|
335
|
-
const { diagramEditorState } = props;
|
|
336
|
-
const renderer = diagramEditorState.renderer;
|
|
337
|
-
const isReadOnly = diagramEditorState.isReadOnly;
|
|
338
|
-
const showDiagramRendererHokeysModal = (): void =>
|
|
339
|
-
diagramEditorState.setShowHotkeyInfosModal(true);
|
|
340
|
-
const hideDiagramRendererHokeysModal = (): void =>
|
|
341
|
-
diagramEditorState.setShowHotkeyInfosModal(false);
|
|
342
|
-
const createModeSwitcher =
|
|
343
|
-
(
|
|
344
|
-
editMode: DIAGRAM_INTERACTION_MODE,
|
|
345
|
-
relationshipMode: DIAGRAM_RELATIONSHIP_EDIT_MODE,
|
|
346
|
-
): (() => void) =>
|
|
347
|
-
(): void => {
|
|
348
|
-
if (!isReadOnly) {
|
|
349
|
-
renderer.changeMode(editMode, relationshipMode);
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
return (
|
|
354
|
-
<div className="diagram-editor__tools">
|
|
355
|
-
<button
|
|
356
|
-
className={clsx('diagram-editor__tool', {
|
|
357
|
-
'diagram-editor__tool--active':
|
|
358
|
-
renderer.interactionMode === DIAGRAM_INTERACTION_MODE.LAYOUT,
|
|
359
|
-
})}
|
|
360
|
-
tabIndex={-1}
|
|
361
|
-
onClick={createModeSwitcher(
|
|
362
|
-
DIAGRAM_INTERACTION_MODE.LAYOUT,
|
|
363
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE,
|
|
364
|
-
)}
|
|
365
|
-
title="View Tool (V)"
|
|
366
|
-
>
|
|
367
|
-
<MousePointerIcon className="diagram-editor__icon--layout" />
|
|
368
|
-
</button>
|
|
369
|
-
<button
|
|
370
|
-
className={clsx('diagram-editor__tool', {
|
|
371
|
-
'diagram-editor__tool--active':
|
|
372
|
-
renderer.interactionMode === DIAGRAM_INTERACTION_MODE.PAN,
|
|
373
|
-
})}
|
|
374
|
-
tabIndex={-1}
|
|
375
|
-
onClick={createModeSwitcher(
|
|
376
|
-
DIAGRAM_INTERACTION_MODE.PAN,
|
|
377
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE,
|
|
378
|
-
)}
|
|
379
|
-
title="Pan Tool (M)"
|
|
380
|
-
>
|
|
381
|
-
<MoveIcon className="diagram-editor__icon--pan" />
|
|
382
|
-
</button>
|
|
383
|
-
<button
|
|
384
|
-
className={clsx('diagram-editor__tool', {
|
|
385
|
-
'diagram-editor__tool--active':
|
|
386
|
-
renderer.interactionMode === DIAGRAM_INTERACTION_MODE.ZOOM_IN,
|
|
387
|
-
})}
|
|
388
|
-
tabIndex={-1}
|
|
389
|
-
title="Zoom In (Z)"
|
|
390
|
-
onClick={createModeSwitcher(
|
|
391
|
-
DIAGRAM_INTERACTION_MODE.ZOOM_IN,
|
|
392
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE,
|
|
393
|
-
)}
|
|
394
|
-
>
|
|
395
|
-
<ZoomInIcon className="diagram-editor__icon--zoom-in" />
|
|
396
|
-
</button>
|
|
397
|
-
<button
|
|
398
|
-
className={clsx('diagram-editor__tool', {
|
|
399
|
-
'diagram-editor__tool--active':
|
|
400
|
-
renderer.interactionMode === DIAGRAM_INTERACTION_MODE.ZOOM_OUT,
|
|
401
|
-
})}
|
|
402
|
-
tabIndex={-1}
|
|
403
|
-
title="Zoom Out (Z)"
|
|
404
|
-
onClick={createModeSwitcher(
|
|
405
|
-
DIAGRAM_INTERACTION_MODE.ZOOM_OUT,
|
|
406
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE,
|
|
407
|
-
)}
|
|
408
|
-
>
|
|
409
|
-
<ZoomOutIcon className="diagram-editor__icon--zoom-out" />
|
|
410
|
-
</button>
|
|
411
|
-
<div className="diagram-editor__tools__divider" />
|
|
412
|
-
<button
|
|
413
|
-
className={clsx('diagram-editor__tool', {
|
|
414
|
-
'diagram-editor__tool--active':
|
|
415
|
-
renderer.interactionMode ===
|
|
416
|
-
DIAGRAM_INTERACTION_MODE.ADD_RELATIONSHIP &&
|
|
417
|
-
renderer.relationshipMode ===
|
|
418
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.PROPERTY,
|
|
419
|
-
})}
|
|
420
|
-
tabIndex={-1}
|
|
421
|
-
title="Property Tool (P)"
|
|
422
|
-
disabled={isReadOnly}
|
|
423
|
-
onClick={createModeSwitcher(
|
|
424
|
-
DIAGRAM_INTERACTION_MODE.ADD_RELATIONSHIP,
|
|
425
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.PROPERTY,
|
|
426
|
-
)}
|
|
427
|
-
>
|
|
428
|
-
<MinusIcon className="diagram-editor__icon--property" />
|
|
429
|
-
</button>
|
|
430
|
-
<button
|
|
431
|
-
className={clsx('diagram-editor__tool', {
|
|
432
|
-
'diagram-editor__tool--active':
|
|
433
|
-
renderer.interactionMode ===
|
|
434
|
-
DIAGRAM_INTERACTION_MODE.ADD_RELATIONSHIP &&
|
|
435
|
-
renderer.relationshipMode ===
|
|
436
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.INHERITANCE,
|
|
437
|
-
})}
|
|
438
|
-
tabIndex={-1}
|
|
439
|
-
title="Inheritance Tool (I)"
|
|
440
|
-
disabled={isReadOnly}
|
|
441
|
-
onClick={createModeSwitcher(
|
|
442
|
-
DIAGRAM_INTERACTION_MODE.ADD_RELATIONSHIP,
|
|
443
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.INHERITANCE,
|
|
444
|
-
)}
|
|
445
|
-
>
|
|
446
|
-
<TriangleIcon className="diagram-editor__icon--inheritance" />
|
|
447
|
-
</button>
|
|
448
|
-
<button
|
|
449
|
-
className={clsx('diagram-editor__tool', {
|
|
450
|
-
// 'diagram-editor__tool--active':
|
|
451
|
-
// diagramRenderer.editMode === DIAGRAM_EDIT_MODE.RELATIONSHIP &&
|
|
452
|
-
// diagramRenderer.relationshipMode ===
|
|
453
|
-
// DIAGRAM_RELATIONSHIP_EDIT_MODE.ASSOCIATION,
|
|
454
|
-
})}
|
|
455
|
-
tabIndex={-1}
|
|
456
|
-
title="Association Tool"
|
|
457
|
-
disabled={true}
|
|
458
|
-
// onClick={changeMode(
|
|
459
|
-
// DIAGRAM_INTERACTION_MODE.ADD_RELATIONSHIP,
|
|
460
|
-
// DIAGRAM_RELATIONSHIP_EDIT_MODE.ASSOCIATION,
|
|
461
|
-
// )}
|
|
462
|
-
>
|
|
463
|
-
<ResizeIcon className="diagram-editor__icon--association" />
|
|
464
|
-
</button>
|
|
465
|
-
<button
|
|
466
|
-
className={clsx('diagram-editor__tool', {
|
|
467
|
-
'diagram-editor__tool--active':
|
|
468
|
-
renderer.interactionMode === DIAGRAM_INTERACTION_MODE.ADD_CLASS,
|
|
469
|
-
})}
|
|
470
|
-
tabIndex={-1}
|
|
471
|
-
title="Add class tool (C)"
|
|
472
|
-
disabled={isReadOnly}
|
|
473
|
-
onClick={createModeSwitcher(
|
|
474
|
-
DIAGRAM_INTERACTION_MODE.ADD_CLASS,
|
|
475
|
-
DIAGRAM_RELATIONSHIP_EDIT_MODE.NONE,
|
|
476
|
-
)}
|
|
477
|
-
>
|
|
478
|
-
<PlusCircleIcon className="diagram-editor__icon--add-class" />
|
|
479
|
-
</button>
|
|
480
|
-
<div className="diagram-editor__tools__divider" />
|
|
481
|
-
<button
|
|
482
|
-
className="diagram-editor__tool"
|
|
483
|
-
tabIndex={-1}
|
|
484
|
-
title="Show Hotkeys"
|
|
485
|
-
onClick={showDiagramRendererHokeysModal}
|
|
486
|
-
>
|
|
487
|
-
<KeyboardIcon className="diagram-editor__icon--hotkey-info" />
|
|
488
|
-
</button>
|
|
489
|
-
<DiagramRendererHotkeyInfosModal
|
|
490
|
-
open={diagramEditorState.showHotkeyInfosModal}
|
|
491
|
-
onClose={hideDiagramRendererHokeysModal}
|
|
492
|
-
/>
|
|
493
|
-
</div>
|
|
494
|
-
);
|
|
495
|
-
},
|
|
496
|
-
);
|
|
497
|
-
|
|
498
|
-
const DiagramEditorClassViewEditor = observer(
|
|
499
|
-
(props: {
|
|
500
|
-
classViewEditorState: DiagramEditorClassViewEditorSidePanelState;
|
|
501
|
-
}) => {
|
|
502
|
-
const { classViewEditorState } = props;
|
|
503
|
-
const editorStore = useEditorStore();
|
|
504
|
-
const classView = classViewEditorState.classView;
|
|
505
|
-
const diagramEditorState = classViewEditorState.diagramEditorState;
|
|
506
|
-
const isReadOnly = diagramEditorState.isReadOnly;
|
|
507
|
-
|
|
508
|
-
// Tabs
|
|
509
|
-
const selectedTab = classViewEditorState.selectedTab;
|
|
510
|
-
const tabs = [
|
|
511
|
-
DIAGRAM_EDITOR_SIDE_PANEL_TAB.ELEMENT,
|
|
512
|
-
DIAGRAM_EDITOR_SIDE_PANEL_TAB.VIEW,
|
|
513
|
-
];
|
|
514
|
-
const changeTab =
|
|
515
|
-
(tab: DIAGRAM_EDITOR_SIDE_PANEL_TAB): (() => void) =>
|
|
516
|
-
(): void => {
|
|
517
|
-
classViewEditorState.setSelectedTab(tab);
|
|
518
|
-
};
|
|
519
|
-
|
|
520
|
-
const redrawOnClassChange = useCallback((): void => {
|
|
521
|
-
cleanUpDeadReferencesInDiagram(
|
|
522
|
-
diagramEditorState.diagram,
|
|
523
|
-
editorStore.graphManagerState.graph,
|
|
524
|
-
);
|
|
525
|
-
diagramEditorState.renderer.render();
|
|
526
|
-
}, [diagramEditorState, editorStore]);
|
|
527
|
-
|
|
528
|
-
const toggleHideProperties = (): void => {
|
|
529
|
-
if (isReadOnly) {
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
classView_setHideProperties(classView, !classView.hideProperties);
|
|
533
|
-
diagramEditorState.renderer.render();
|
|
534
|
-
};
|
|
535
|
-
const toggleHideTaggedValues = (): void => {
|
|
536
|
-
if (isReadOnly) {
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
classView_setHideTaggedValues(classView, !classView.hideTaggedValues);
|
|
540
|
-
diagramEditorState.renderer.render();
|
|
541
|
-
};
|
|
542
|
-
const toggleHideStereotypes = (): void => {
|
|
543
|
-
if (isReadOnly) {
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
classView_setHideStereotypes(classView, !classView.hideStereotypes);
|
|
547
|
-
diagramEditorState.renderer.render();
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
return (
|
|
551
|
-
<div className="diagram-editor__class-view-editor">
|
|
552
|
-
<div className="diagram-editor__class-view-editor__header">
|
|
553
|
-
<div className="diagram-editor__class-view-editor__header__tabs">
|
|
554
|
-
{tabs.map((tab) => (
|
|
555
|
-
<div
|
|
556
|
-
key={tab}
|
|
557
|
-
onClick={changeTab(tab)}
|
|
558
|
-
className={clsx(
|
|
559
|
-
'diagram-editor__class-view-editor__header__tab',
|
|
560
|
-
{
|
|
561
|
-
'diagram-editor__class-view-editor__header__tab--active':
|
|
562
|
-
tab === selectedTab,
|
|
563
|
-
},
|
|
564
|
-
)}
|
|
565
|
-
>
|
|
566
|
-
{prettyCONSTName(tab)}
|
|
567
|
-
</div>
|
|
568
|
-
))}
|
|
569
|
-
</div>
|
|
570
|
-
</div>
|
|
571
|
-
<div className="diagram-editor__class-view-editor__content">
|
|
572
|
-
{DIAGRAM_EDITOR_SIDE_PANEL_TAB.ELEMENT === selectedTab && (
|
|
573
|
-
<ClassFormEditor
|
|
574
|
-
_class={classViewEditorState.classEditorState.class}
|
|
575
|
-
editorState={classViewEditorState.classEditorState}
|
|
576
|
-
onHashChange={redrawOnClassChange}
|
|
577
|
-
/>
|
|
578
|
-
)}
|
|
579
|
-
{DIAGRAM_EDITOR_SIDE_PANEL_TAB.VIEW === selectedTab && (
|
|
580
|
-
<div className="panel__content__form diagram-editor__class-view-editor__content__form">
|
|
581
|
-
<div className="panel__content__form__section">
|
|
582
|
-
{/* Hide properties */}
|
|
583
|
-
<div
|
|
584
|
-
className={clsx('panel__content__form__section__toggler')}
|
|
585
|
-
onClick={toggleHideProperties}
|
|
586
|
-
>
|
|
587
|
-
<button
|
|
588
|
-
className={clsx(
|
|
589
|
-
'panel__content__form__section__toggler__btn',
|
|
590
|
-
{
|
|
591
|
-
'panel__content__form__section__toggler__btn--toggled':
|
|
592
|
-
classView.hideProperties,
|
|
593
|
-
},
|
|
594
|
-
)}
|
|
595
|
-
disabled={isReadOnly}
|
|
596
|
-
>
|
|
597
|
-
{classView.hideProperties ? (
|
|
598
|
-
<CheckSquareIcon />
|
|
599
|
-
) : (
|
|
600
|
-
<SquareIcon />
|
|
601
|
-
)}
|
|
602
|
-
</button>
|
|
603
|
-
<div className="panel__content__form__section__toggler__prompt">
|
|
604
|
-
Specifies if properties should be hidden
|
|
605
|
-
</div>
|
|
606
|
-
</div>
|
|
607
|
-
{/* Hide tagged-values */}
|
|
608
|
-
<div
|
|
609
|
-
className={clsx('panel__content__form__section__toggler')}
|
|
610
|
-
onClick={toggleHideTaggedValues}
|
|
611
|
-
>
|
|
612
|
-
<button
|
|
613
|
-
className={clsx(
|
|
614
|
-
'panel__content__form__section__toggler__btn',
|
|
615
|
-
{
|
|
616
|
-
'panel__content__form__section__toggler__btn--toggled':
|
|
617
|
-
classView.hideTaggedValues,
|
|
618
|
-
},
|
|
619
|
-
)}
|
|
620
|
-
disabled={isReadOnly}
|
|
621
|
-
>
|
|
622
|
-
{classView.hideTaggedValues ? (
|
|
623
|
-
<CheckSquareIcon />
|
|
624
|
-
) : (
|
|
625
|
-
<SquareIcon />
|
|
626
|
-
)}
|
|
627
|
-
</button>
|
|
628
|
-
<div className="panel__content__form__section__toggler__prompt">
|
|
629
|
-
Specifies if tagged values should be hidden
|
|
630
|
-
</div>
|
|
631
|
-
</div>
|
|
632
|
-
{/* Hide stereotypes */}
|
|
633
|
-
<div
|
|
634
|
-
className={clsx('panel__content__form__section__toggler')}
|
|
635
|
-
onClick={toggleHideStereotypes}
|
|
636
|
-
>
|
|
637
|
-
<button
|
|
638
|
-
className={clsx(
|
|
639
|
-
'panel__content__form__section__toggler__btn',
|
|
640
|
-
{
|
|
641
|
-
'panel__content__form__section__toggler__btn--toggled':
|
|
642
|
-
classView.hideStereotypes,
|
|
643
|
-
},
|
|
644
|
-
)}
|
|
645
|
-
disabled={isReadOnly}
|
|
646
|
-
>
|
|
647
|
-
{classView.hideStereotypes ? (
|
|
648
|
-
<CheckSquareIcon />
|
|
649
|
-
) : (
|
|
650
|
-
<SquareIcon />
|
|
651
|
-
)}
|
|
652
|
-
</button>
|
|
653
|
-
<div className="panel__content__form__section__toggler__prompt">
|
|
654
|
-
Specifies if stereotypes should be hidden
|
|
655
|
-
</div>
|
|
656
|
-
</div>
|
|
657
|
-
</div>
|
|
658
|
-
</div>
|
|
659
|
-
)}
|
|
660
|
-
</div>
|
|
661
|
-
</div>
|
|
662
|
-
);
|
|
663
|
-
},
|
|
664
|
-
);
|
|
665
|
-
|
|
666
|
-
const DiagramEditorOverlay = observer(
|
|
667
|
-
(props: { diagramEditorState: DiagramEditorState }) => {
|
|
668
|
-
const { diagramEditorState } = props;
|
|
669
|
-
const sidePanelState = diagramEditorState.sidePanelState;
|
|
670
|
-
|
|
671
|
-
const resizeSidePanel = (handleProps: ResizablePanelHandlerProps): void =>
|
|
672
|
-
diagramEditorState.sidePanelDisplayState.setSize(
|
|
673
|
-
(handleProps.domElement as HTMLDivElement).getBoundingClientRect()
|
|
674
|
-
.width,
|
|
675
|
-
);
|
|
676
|
-
|
|
677
|
-
// layout
|
|
678
|
-
const sidePanelCollapsiblePanelGroupProps = getCollapsiblePanelGroupProps(
|
|
679
|
-
diagramEditorState.sidePanelDisplayState.size === 0,
|
|
680
|
-
{
|
|
681
|
-
classes: ['diagram-editor__overlay__panel'],
|
|
682
|
-
onStopResize: resizeSidePanel,
|
|
683
|
-
size: diagramEditorState.sidePanelDisplayState.size,
|
|
684
|
-
},
|
|
685
|
-
);
|
|
686
|
-
|
|
687
|
-
return (
|
|
688
|
-
<ResizablePanelGroup
|
|
689
|
-
className="diagram-editor__overlay"
|
|
690
|
-
orientation="vertical"
|
|
691
|
-
>
|
|
692
|
-
<ResizablePanel
|
|
693
|
-
{...sidePanelCollapsiblePanelGroupProps.remainingPanel}
|
|
694
|
-
minSize={300}
|
|
695
|
-
>
|
|
696
|
-
<div className="diagram-editor__view-finder" />
|
|
697
|
-
</ResizablePanel>
|
|
698
|
-
<ResizablePanelSplitter className="diagram-editor__overlay__panel-resizer" />
|
|
699
|
-
<ResizablePanel
|
|
700
|
-
{...sidePanelCollapsiblePanelGroupProps.collapsiblePanel}
|
|
701
|
-
direction={-1}
|
|
702
|
-
>
|
|
703
|
-
<div className="panel diagram-editor__side-panel">
|
|
704
|
-
{sidePanelState instanceof
|
|
705
|
-
DiagramEditorClassViewEditorSidePanelState && (
|
|
706
|
-
<DiagramEditorClassViewEditor
|
|
707
|
-
classViewEditorState={sidePanelState}
|
|
708
|
-
/>
|
|
709
|
-
)}
|
|
710
|
-
{!sidePanelState && (
|
|
711
|
-
<BlankPanelContent>No element selected</BlankPanelContent>
|
|
712
|
-
)}
|
|
713
|
-
</div>
|
|
714
|
-
</ResizablePanel>
|
|
715
|
-
</ResizablePanelGroup>
|
|
716
|
-
);
|
|
717
|
-
},
|
|
718
|
-
);
|
|
719
|
-
|
|
720
|
-
const DiagramEditorInlineClassRenamerContent = observer(
|
|
721
|
-
(props: {
|
|
722
|
-
inlineClassRenamerState: DiagramEditorInlineClassRenamerState;
|
|
723
|
-
}) => {
|
|
724
|
-
const { inlineClassRenamerState } = props;
|
|
725
|
-
const editorStore = useEditorStore();
|
|
726
|
-
const applicationStore = useApplicationStore();
|
|
727
|
-
const diagramEditorState = inlineClassRenamerState.diagramEditorState;
|
|
728
|
-
const _class = inlineClassRenamerState.classView.class.value;
|
|
729
|
-
const isReadOnly = diagramEditorState.isReadOnly;
|
|
730
|
-
const [name, setName] = useState(_class.name);
|
|
731
|
-
const [packagePath] = resolvePackagePathAndElementName(_class.path);
|
|
732
|
-
const newClassPath = createPath(packagePath, name);
|
|
733
|
-
const isClassNameNonEmpty = name !== '';
|
|
734
|
-
const isClassNameValid = isValidPathIdentifier(name);
|
|
735
|
-
const existingElement =
|
|
736
|
-
editorStore.graphManagerState.graph.getNullableElement(newClassPath);
|
|
737
|
-
const isClassNameUnique = !existingElement || existingElement === _class;
|
|
738
|
-
// const class
|
|
739
|
-
const classCreationValidationErrorMessage = !isClassNameNonEmpty
|
|
740
|
-
? `Class name cannot be empty`
|
|
741
|
-
: !isClassNameValid
|
|
742
|
-
? `Class name is not valid`
|
|
743
|
-
: !isClassNameUnique
|
|
744
|
-
? `Element of the same name already existed`
|
|
745
|
-
: undefined;
|
|
746
|
-
const canRenameClass =
|
|
747
|
-
isClassNameNonEmpty && isClassNameValid && isClassNameUnique;
|
|
748
|
-
|
|
749
|
-
const close = (event: React.MouseEvent<HTMLButtonElement>): void => {
|
|
750
|
-
event.preventDefault();
|
|
751
|
-
if (canRenameClass) {
|
|
752
|
-
diagramEditorState.setInlineClassRenamerState(undefined);
|
|
753
|
-
flowResult(
|
|
754
|
-
editorStore.graphEditorMode.renameElement(_class, newClassPath),
|
|
755
|
-
).catch(applicationStore.alertUnhandledError);
|
|
756
|
-
}
|
|
757
|
-
};
|
|
758
|
-
const pathInputRef = useRef<HTMLInputElement>(null);
|
|
759
|
-
|
|
760
|
-
const changePath: React.ChangeEventHandler<HTMLInputElement> = (event) =>
|
|
761
|
-
setName(event.target.value);
|
|
762
|
-
|
|
763
|
-
useEffect(() => {
|
|
764
|
-
pathInputRef.current?.focus();
|
|
765
|
-
}, [inlineClassRenamerState]);
|
|
766
|
-
|
|
767
|
-
return (
|
|
768
|
-
<form className="diagram-editor__inline-class-creator">
|
|
769
|
-
<div className="input-group">
|
|
770
|
-
<input
|
|
771
|
-
className="diagram-editor__inline-class-creator__path input-group__input input--dark"
|
|
772
|
-
ref={pathInputRef}
|
|
773
|
-
disabled={isReadOnly}
|
|
774
|
-
value={name}
|
|
775
|
-
placeholder="Enter class name"
|
|
776
|
-
onChange={changePath}
|
|
777
|
-
/>
|
|
778
|
-
{classCreationValidationErrorMessage && (
|
|
779
|
-
<div className="input-group__error-message">
|
|
780
|
-
{classCreationValidationErrorMessage}
|
|
781
|
-
</div>
|
|
782
|
-
)}
|
|
783
|
-
</div>
|
|
784
|
-
<button
|
|
785
|
-
type="submit"
|
|
786
|
-
className="diagram-editor__inline-class-creator__close-btn"
|
|
787
|
-
onClick={close}
|
|
788
|
-
/>
|
|
789
|
-
</form>
|
|
790
|
-
);
|
|
791
|
-
},
|
|
792
|
-
);
|
|
793
|
-
|
|
794
|
-
const DiagramEditorInlineClassRenamer = observer(
|
|
795
|
-
(props: { diagramEditorState: DiagramEditorState }) => {
|
|
796
|
-
const { diagramEditorState } = props;
|
|
797
|
-
const closeEditor = (): void => {
|
|
798
|
-
diagramEditorState.setInlineClassRenamerState(undefined);
|
|
799
|
-
};
|
|
800
|
-
const inlineClassRenamerState = diagramEditorState.inlineClassRenamerState;
|
|
801
|
-
const anchorPositionPoint = inlineClassRenamerState
|
|
802
|
-
? diagramEditorState.renderer.canvasCoordinateToEventCoordinate(
|
|
803
|
-
diagramEditorState.renderer.modelCoordinateToCanvasCoordinate(
|
|
804
|
-
inlineClassRenamerState.point,
|
|
805
|
-
),
|
|
806
|
-
)
|
|
807
|
-
: new Point(0, 0);
|
|
808
|
-
|
|
809
|
-
return (
|
|
810
|
-
<BasePopover
|
|
811
|
-
onClose={closeEditor}
|
|
812
|
-
anchorPosition={{
|
|
813
|
-
left: anchorPositionPoint.x,
|
|
814
|
-
top: anchorPositionPoint.y,
|
|
815
|
-
}}
|
|
816
|
-
anchorReference="anchorPosition"
|
|
817
|
-
open={Boolean(inlineClassRenamerState)}
|
|
818
|
-
BackdropProps={{
|
|
819
|
-
invisible: true,
|
|
820
|
-
}}
|
|
821
|
-
elevation={0}
|
|
822
|
-
marginThreshold={0}
|
|
823
|
-
disableRestoreFocus={true}
|
|
824
|
-
>
|
|
825
|
-
<div className="diagram-editor__inline-class-creator__container">
|
|
826
|
-
{inlineClassRenamerState && (
|
|
827
|
-
<DiagramEditorInlineClassRenamerContent
|
|
828
|
-
inlineClassRenamerState={inlineClassRenamerState}
|
|
829
|
-
/>
|
|
830
|
-
)}
|
|
831
|
-
</div>
|
|
832
|
-
</BasePopover>
|
|
833
|
-
);
|
|
834
|
-
},
|
|
835
|
-
);
|
|
836
|
-
|
|
837
|
-
const DiagramEditorInlineClassCreatorContent = observer(
|
|
838
|
-
(props: {
|
|
839
|
-
inlineClassCreatorState: DiagramEditorInlineClassCreatorState;
|
|
840
|
-
}) => {
|
|
841
|
-
const { inlineClassCreatorState } = props;
|
|
842
|
-
const editorStore = useEditorStore();
|
|
843
|
-
const applicationStore = useApplicationStore();
|
|
844
|
-
const diagramEditorState = inlineClassCreatorState.diagramEditorState;
|
|
845
|
-
const isReadOnly = diagramEditorState.isReadOnly;
|
|
846
|
-
const [path, setPath] = useState(
|
|
847
|
-
`${
|
|
848
|
-
diagramEditorState.diagram.package
|
|
849
|
-
? `${diagramEditorState.diagram.package.path}${ELEMENT_PATH_DELIMITER}`
|
|
850
|
-
: ''
|
|
851
|
-
}Class_${editorStore.graphManagerState.graph.ownClasses.length + 1}`,
|
|
852
|
-
);
|
|
853
|
-
const isClassPathNonEmpty = path !== '';
|
|
854
|
-
const isNotTopLevelClass = path.includes(ELEMENT_PATH_DELIMITER);
|
|
855
|
-
const isValidPath = isValidFullPath(path);
|
|
856
|
-
const isClassUnique =
|
|
857
|
-
!editorStore.graphManagerState.graph.getNullableElement(path);
|
|
858
|
-
const classCreationValidationErrorMessage = !isClassPathNonEmpty
|
|
859
|
-
? `Class path cannot be empty`
|
|
860
|
-
: !isNotTopLevelClass
|
|
861
|
-
? `Creating top level class is not allowed`
|
|
862
|
-
: !isValidPath
|
|
863
|
-
? `Class path is not valid`
|
|
864
|
-
: !isClassUnique
|
|
865
|
-
? `Class already existed`
|
|
866
|
-
: undefined;
|
|
867
|
-
const canCreateClass =
|
|
868
|
-
isClassPathNonEmpty && isNotTopLevelClass && isValidPath && isClassUnique;
|
|
869
|
-
|
|
870
|
-
const createClass = async (
|
|
871
|
-
event: React.MouseEvent<HTMLButtonElement>,
|
|
872
|
-
): Promise<void> => {
|
|
873
|
-
event.preventDefault();
|
|
874
|
-
if (canCreateClass) {
|
|
875
|
-
diagramEditorState.setInlineClassCreatorState(undefined);
|
|
876
|
-
const [packagePath, name] = resolvePackagePathAndElementName(path);
|
|
877
|
-
const _class = new Class(name);
|
|
878
|
-
await flowResult(
|
|
879
|
-
editorStore.graphEditorMode.addElement(_class, packagePath, false),
|
|
880
|
-
);
|
|
881
|
-
diagramEditorState.renderer.addClassView(
|
|
882
|
-
_class,
|
|
883
|
-
inlineClassCreatorState.point,
|
|
884
|
-
);
|
|
885
|
-
}
|
|
886
|
-
};
|
|
887
|
-
const close = (event: React.MouseEvent<HTMLButtonElement>): void => {
|
|
888
|
-
createClass(event).catch(applicationStore.alertUnhandledError);
|
|
889
|
-
};
|
|
890
|
-
const pathInputRef = useRef<HTMLInputElement>(null);
|
|
891
|
-
|
|
892
|
-
const changePath: React.ChangeEventHandler<HTMLInputElement> = (event) =>
|
|
893
|
-
setPath(event.target.value);
|
|
894
|
-
|
|
895
|
-
useEffect(() => {
|
|
896
|
-
pathInputRef.current?.focus();
|
|
897
|
-
}, [inlineClassCreatorState]);
|
|
898
|
-
|
|
899
|
-
return (
|
|
900
|
-
<form className="diagram-editor__inline-class-creator">
|
|
901
|
-
<div className="input-group">
|
|
902
|
-
<input
|
|
903
|
-
className="diagram-editor__inline-class-creator__path input-group__input input--dark"
|
|
904
|
-
ref={pathInputRef}
|
|
905
|
-
disabled={isReadOnly}
|
|
906
|
-
value={path}
|
|
907
|
-
placeholder="Enter class path"
|
|
908
|
-
onChange={changePath}
|
|
909
|
-
/>
|
|
910
|
-
{classCreationValidationErrorMessage && (
|
|
911
|
-
<div className="input-group__error-message">
|
|
912
|
-
{classCreationValidationErrorMessage}
|
|
913
|
-
</div>
|
|
914
|
-
)}
|
|
915
|
-
</div>
|
|
916
|
-
<button
|
|
917
|
-
type="submit"
|
|
918
|
-
className="diagram-editor__inline-class-creator__close-btn"
|
|
919
|
-
onClick={close}
|
|
920
|
-
/>
|
|
921
|
-
</form>
|
|
922
|
-
);
|
|
923
|
-
},
|
|
924
|
-
);
|
|
925
|
-
|
|
926
|
-
const DiagramEditorInlineClassCreator = observer(
|
|
927
|
-
(props: { diagramEditorState: DiagramEditorState }) => {
|
|
928
|
-
const { diagramEditorState } = props;
|
|
929
|
-
const closeEditor = (): void => {
|
|
930
|
-
diagramEditorState.setInlineClassCreatorState(undefined);
|
|
931
|
-
};
|
|
932
|
-
const inlineClassCreatorState = diagramEditorState.inlineClassCreatorState;
|
|
933
|
-
const anchorPositionPoint = inlineClassCreatorState
|
|
934
|
-
? diagramEditorState.renderer.canvasCoordinateToEventCoordinate(
|
|
935
|
-
diagramEditorState.renderer.modelCoordinateToCanvasCoordinate(
|
|
936
|
-
inlineClassCreatorState.point,
|
|
937
|
-
),
|
|
938
|
-
)
|
|
939
|
-
: new Point(0, 0);
|
|
940
|
-
|
|
941
|
-
return (
|
|
942
|
-
<BasePopover
|
|
943
|
-
onClose={closeEditor}
|
|
944
|
-
anchorPosition={{
|
|
945
|
-
left: anchorPositionPoint.x,
|
|
946
|
-
top: anchorPositionPoint.y,
|
|
947
|
-
}}
|
|
948
|
-
anchorReference="anchorPosition"
|
|
949
|
-
open={Boolean(inlineClassCreatorState)}
|
|
950
|
-
BackdropProps={{
|
|
951
|
-
invisible: true,
|
|
952
|
-
}}
|
|
953
|
-
elevation={0}
|
|
954
|
-
marginThreshold={0}
|
|
955
|
-
disableRestoreFocus={true}
|
|
956
|
-
>
|
|
957
|
-
<div className="diagram-editor__inline-class-creator__container">
|
|
958
|
-
{inlineClassCreatorState && (
|
|
959
|
-
<DiagramEditorInlineClassCreatorContent
|
|
960
|
-
inlineClassCreatorState={inlineClassCreatorState}
|
|
961
|
-
/>
|
|
962
|
-
)}
|
|
963
|
-
</div>
|
|
964
|
-
</BasePopover>
|
|
965
|
-
);
|
|
966
|
-
},
|
|
967
|
-
);
|
|
968
|
-
|
|
969
|
-
const DiagramEditorInlinePropertyMultiplicityEditor = observer(
|
|
970
|
-
(props: {
|
|
971
|
-
value: Multiplicity;
|
|
972
|
-
updateValue: (val: Multiplicity) => void;
|
|
973
|
-
isReadOnly: boolean;
|
|
974
|
-
}) => {
|
|
975
|
-
const { value, updateValue, isReadOnly } = props;
|
|
976
|
-
const [lowerBound, setLowerBound] = useState<string | number>(
|
|
977
|
-
value.lowerBound,
|
|
978
|
-
);
|
|
979
|
-
const [upperBound, setUpperBound] = useState<string | number>(
|
|
980
|
-
value.upperBound ?? MULTIPLICITY_INFINITE,
|
|
981
|
-
);
|
|
982
|
-
const editorStore = useEditorStore();
|
|
983
|
-
const updateMultiplicity = (
|
|
984
|
-
lower: number | string,
|
|
985
|
-
upper: number | string,
|
|
986
|
-
): void => {
|
|
987
|
-
const lBound = typeof lower === 'number' ? lower : parseInt(lower, 10);
|
|
988
|
-
const uBound =
|
|
989
|
-
upper === MULTIPLICITY_INFINITE
|
|
990
|
-
? undefined
|
|
991
|
-
: typeof upper === 'number'
|
|
992
|
-
? upper
|
|
993
|
-
: parseInt(upper, 10);
|
|
994
|
-
if (!isNaN(lBound) && (uBound === undefined || !isNaN(uBound))) {
|
|
995
|
-
updateValue(
|
|
996
|
-
editorStore.graphManagerState.graph.getMultiplicity(lBound, uBound),
|
|
997
|
-
);
|
|
998
|
-
}
|
|
999
|
-
};
|
|
1000
|
-
const changeLowerBound: React.ChangeEventHandler<HTMLInputElement> = (
|
|
1001
|
-
event,
|
|
1002
|
-
) => {
|
|
1003
|
-
setLowerBound(event.target.value);
|
|
1004
|
-
updateMultiplicity(event.target.value, upperBound);
|
|
1005
|
-
};
|
|
1006
|
-
const changeUpperBound: React.ChangeEventHandler<HTMLInputElement> = (
|
|
1007
|
-
event,
|
|
1008
|
-
) => {
|
|
1009
|
-
setUpperBound(event.target.value);
|
|
1010
|
-
updateMultiplicity(lowerBound, event.target.value);
|
|
1011
|
-
};
|
|
1012
|
-
|
|
1013
|
-
return (
|
|
1014
|
-
<div className="diagram-editor__inline-property-editor__multiplicity-editor">
|
|
1015
|
-
<input
|
|
1016
|
-
className="diagram-editor__inline-property-editor__multiplicity-editor__bound input--dark"
|
|
1017
|
-
disabled={isReadOnly}
|
|
1018
|
-
spellCheck={false}
|
|
1019
|
-
value={lowerBound}
|
|
1020
|
-
onChange={changeLowerBound}
|
|
1021
|
-
/>
|
|
1022
|
-
<div className="diagram-editor__inline-property-editor__multiplicity-editor__range">
|
|
1023
|
-
..
|
|
1024
|
-
</div>
|
|
1025
|
-
<input
|
|
1026
|
-
className="diagram-editor__inline-property-editor__multiplicity-editor__bound input--dark"
|
|
1027
|
-
disabled={isReadOnly}
|
|
1028
|
-
spellCheck={false}
|
|
1029
|
-
value={upperBound}
|
|
1030
|
-
onChange={changeUpperBound}
|
|
1031
|
-
/>
|
|
1032
|
-
</div>
|
|
1033
|
-
);
|
|
1034
|
-
},
|
|
1035
|
-
);
|
|
1036
|
-
|
|
1037
|
-
const DiagramEditorInlinePropertyEditorContent = observer(
|
|
1038
|
-
(props: {
|
|
1039
|
-
inlinePropertyEditorState: DiagramEditorInlinePropertyEditorState;
|
|
1040
|
-
}) => {
|
|
1041
|
-
const { inlinePropertyEditorState } = props;
|
|
1042
|
-
const editorStore = useEditorStore();
|
|
1043
|
-
const applicationStore = editorStore.applicationStore;
|
|
1044
|
-
const diagramEditorState = inlinePropertyEditorState.diagramEditorState;
|
|
1045
|
-
const isReadOnly = diagramEditorState.isReadOnly;
|
|
1046
|
-
const propertyNameInputRef = useRef<HTMLInputElement>(null);
|
|
1047
|
-
const property = inlinePropertyEditorState.property.value;
|
|
1048
|
-
const close = (event: React.MouseEvent<HTMLButtonElement>): void => {
|
|
1049
|
-
event.preventDefault();
|
|
1050
|
-
diagramEditorState.setInlinePropertyEditorState(undefined);
|
|
1051
|
-
};
|
|
1052
|
-
|
|
1053
|
-
const changePropertyName: React.ChangeEventHandler<HTMLInputElement> = (
|
|
1054
|
-
event,
|
|
1055
|
-
) => {
|
|
1056
|
-
if (property instanceof DerivedProperty || property instanceof Property) {
|
|
1057
|
-
property_setName(property, event.target.value);
|
|
1058
|
-
diagramEditorState.renderer.render();
|
|
1059
|
-
}
|
|
1060
|
-
};
|
|
1061
|
-
|
|
1062
|
-
const changeMultiplicity = (val: Multiplicity): void => {
|
|
1063
|
-
if (property instanceof DerivedProperty || property instanceof Property) {
|
|
1064
|
-
property_setMultiplicity(property, val);
|
|
1065
|
-
diagramEditorState.renderer.render();
|
|
1066
|
-
}
|
|
1067
|
-
};
|
|
1068
|
-
|
|
1069
|
-
// Type
|
|
1070
|
-
const currentPropertyType = property.genericType.value.rawType;
|
|
1071
|
-
const propertyTypeOptions =
|
|
1072
|
-
editorStore.graphManagerState.usableClassPropertyTypes.map(
|
|
1073
|
-
buildElementOption,
|
|
1074
|
-
);
|
|
1075
|
-
const propertyTypeFilterOption = createFilter({
|
|
1076
|
-
ignoreCase: true,
|
|
1077
|
-
ignoreAccents: false,
|
|
1078
|
-
stringify: (option: { data: PackageableElementOption<Type> }): string =>
|
|
1079
|
-
option.data.value.path,
|
|
1080
|
-
});
|
|
1081
|
-
const selectedPropertyType = {
|
|
1082
|
-
value: currentPropertyType,
|
|
1083
|
-
label: currentPropertyType.name,
|
|
1084
|
-
};
|
|
1085
|
-
const changePropertyType = (val: PackageableElementOption<Type>): void => {
|
|
1086
|
-
if (property instanceof Property || property instanceof DerivedProperty) {
|
|
1087
|
-
property_setGenericType(property, new GenericType(val.value));
|
|
1088
|
-
}
|
|
1089
|
-
};
|
|
1090
|
-
|
|
1091
|
-
useEffect(() => {
|
|
1092
|
-
propertyNameInputRef.current?.focus();
|
|
1093
|
-
}, [inlinePropertyEditorState]);
|
|
1094
|
-
|
|
1095
|
-
return (
|
|
1096
|
-
<form
|
|
1097
|
-
className={clsx('diagram-editor__inline-property-editor', {
|
|
1098
|
-
'diagram-editor__inline-property-editor--with-type':
|
|
1099
|
-
!inlinePropertyEditorState.isEditingPropertyView,
|
|
1100
|
-
})}
|
|
1101
|
-
>
|
|
1102
|
-
<input
|
|
1103
|
-
className="diagram-editor__inline-property-editor__name input--dark"
|
|
1104
|
-
ref={propertyNameInputRef}
|
|
1105
|
-
disabled={isReadOnly}
|
|
1106
|
-
value={property.name}
|
|
1107
|
-
onChange={changePropertyName}
|
|
1108
|
-
/>
|
|
1109
|
-
{!inlinePropertyEditorState.isEditingPropertyView && (
|
|
1110
|
-
<CustomSelectorInput
|
|
1111
|
-
className="diagram-editor__inline-property-editor__type"
|
|
1112
|
-
disabled={isReadOnly}
|
|
1113
|
-
options={propertyTypeOptions}
|
|
1114
|
-
onChange={changePropertyType}
|
|
1115
|
-
value={selectedPropertyType}
|
|
1116
|
-
placeholder="Choose a type..."
|
|
1117
|
-
darkMode={
|
|
1118
|
-
!applicationStore.layoutService
|
|
1119
|
-
.TEMPORARY__isLightColorThemeEnabled
|
|
1120
|
-
}
|
|
1121
|
-
filterOption={propertyTypeFilterOption}
|
|
1122
|
-
/>
|
|
1123
|
-
)}
|
|
1124
|
-
<DiagramEditorInlinePropertyMultiplicityEditor
|
|
1125
|
-
isReadOnly={isReadOnly}
|
|
1126
|
-
value={property.multiplicity}
|
|
1127
|
-
updateValue={changeMultiplicity}
|
|
1128
|
-
/>
|
|
1129
|
-
<button
|
|
1130
|
-
type="submit"
|
|
1131
|
-
className="diagram-editor__inline-property-editor__close-btn"
|
|
1132
|
-
onClick={close}
|
|
1133
|
-
/>
|
|
1134
|
-
</form>
|
|
1135
|
-
);
|
|
1136
|
-
},
|
|
1137
|
-
);
|
|
1138
|
-
|
|
1139
|
-
const DiagramEditorInlinePropertyEditor = observer(
|
|
1140
|
-
(props: { diagramEditorState: DiagramEditorState }) => {
|
|
1141
|
-
const { diagramEditorState } = props;
|
|
1142
|
-
const closeEditor = (): void => {
|
|
1143
|
-
diagramEditorState.setInlinePropertyEditorState(undefined);
|
|
1144
|
-
};
|
|
1145
|
-
const inlinePropertyEditorState =
|
|
1146
|
-
diagramEditorState.inlinePropertyEditorState;
|
|
1147
|
-
const anchorPositionPoint = inlinePropertyEditorState
|
|
1148
|
-
? diagramEditorState.renderer.canvasCoordinateToEventCoordinate(
|
|
1149
|
-
diagramEditorState.renderer.modelCoordinateToCanvasCoordinate(
|
|
1150
|
-
inlinePropertyEditorState.point,
|
|
1151
|
-
),
|
|
1152
|
-
)
|
|
1153
|
-
: new Point(0, 0);
|
|
1154
|
-
|
|
1155
|
-
return (
|
|
1156
|
-
<BasePopover
|
|
1157
|
-
onClose={closeEditor}
|
|
1158
|
-
anchorPosition={{
|
|
1159
|
-
left: anchorPositionPoint.x,
|
|
1160
|
-
top: anchorPositionPoint.y,
|
|
1161
|
-
}}
|
|
1162
|
-
anchorReference="anchorPosition"
|
|
1163
|
-
open={Boolean(inlinePropertyEditorState)}
|
|
1164
|
-
BackdropProps={{
|
|
1165
|
-
invisible: true,
|
|
1166
|
-
}}
|
|
1167
|
-
elevation={0}
|
|
1168
|
-
marginThreshold={0}
|
|
1169
|
-
disableRestoreFocus={true}
|
|
1170
|
-
>
|
|
1171
|
-
<div className="diagram-editor__inline-property-editor__container">
|
|
1172
|
-
{inlinePropertyEditorState && (
|
|
1173
|
-
<DiagramEditorInlinePropertyEditorContent
|
|
1174
|
-
inlinePropertyEditorState={inlinePropertyEditorState}
|
|
1175
|
-
/>
|
|
1176
|
-
)}
|
|
1177
|
-
</div>
|
|
1178
|
-
</BasePopover>
|
|
1179
|
-
);
|
|
1180
|
-
},
|
|
1181
|
-
);
|
|
1182
|
-
|
|
1183
|
-
const DiagramEditorDiagramCanvas = observer(
|
|
1184
|
-
forwardRef<
|
|
1185
|
-
HTMLDivElement,
|
|
1186
|
-
{
|
|
1187
|
-
diagramEditorState: DiagramEditorState;
|
|
1188
|
-
}
|
|
1189
|
-
>(function DiagramEditorDiagramCanvas(props, _ref) {
|
|
1190
|
-
const { diagramEditorState } = props;
|
|
1191
|
-
const ref = _ref as React.RefObject<HTMLDivElement>;
|
|
1192
|
-
const isReadOnly = diagramEditorState.isReadOnly;
|
|
1193
|
-
|
|
1194
|
-
const { width, height } = useResizeDetector<HTMLDivElement>({
|
|
1195
|
-
refreshMode: 'debounce',
|
|
1196
|
-
refreshRate: 50,
|
|
1197
|
-
targetRef: ref,
|
|
1198
|
-
});
|
|
1199
|
-
|
|
1200
|
-
useEffect(() => {
|
|
1201
|
-
const renderer = new DiagramRenderer(
|
|
1202
|
-
ref.current,
|
|
1203
|
-
diagramEditorState.diagram,
|
|
1204
|
-
);
|
|
1205
|
-
diagramEditorState.setRenderer(renderer);
|
|
1206
|
-
diagramEditorState.setupRenderer();
|
|
1207
|
-
renderer.render({ initial: true });
|
|
1208
|
-
}, [ref, diagramEditorState]);
|
|
1209
|
-
|
|
1210
|
-
useEffect(() => {
|
|
1211
|
-
// since after the diagram render is initialized, we start
|
|
1212
|
-
// showing the toolbar and the header, which causes the auto-zoom fit
|
|
1213
|
-
// to be off, we need to call this method again
|
|
1214
|
-
if (diagramEditorState.isDiagramRendererInitialized) {
|
|
1215
|
-
diagramEditorState.renderer.render({ initial: true });
|
|
1216
|
-
}
|
|
1217
|
-
}, [diagramEditorState, diagramEditorState.isDiagramRendererInitialized]);
|
|
1218
|
-
|
|
1219
|
-
useEffect(() => {
|
|
1220
|
-
if (diagramEditorState.isDiagramRendererInitialized) {
|
|
1221
|
-
diagramEditorState.renderer.refresh();
|
|
1222
|
-
}
|
|
1223
|
-
}, [diagramEditorState, width, height]);
|
|
1224
|
-
|
|
1225
|
-
// Drag and Drop
|
|
1226
|
-
const handleDrop = useCallback(
|
|
1227
|
-
(item: ElementDragSource, monitor: DropTargetMonitor): void => {
|
|
1228
|
-
if (!isReadOnly) {
|
|
1229
|
-
if (item instanceof ElementDragSource) {
|
|
1230
|
-
if (item.data.packageableElement instanceof Class) {
|
|
1231
|
-
const dropPosition = monitor.getClientOffset();
|
|
1232
|
-
diagramEditorState.renderer.addClassView(
|
|
1233
|
-
item.data.packageableElement,
|
|
1234
|
-
dropPosition
|
|
1235
|
-
? diagramEditorState.renderer.canvasCoordinateToModelCoordinate(
|
|
1236
|
-
diagramEditorState.renderer.eventCoordinateToCanvasCoordinate(
|
|
1237
|
-
new Point(dropPosition.x, dropPosition.y),
|
|
1238
|
-
),
|
|
1239
|
-
)
|
|
1240
|
-
: undefined,
|
|
1241
|
-
);
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
},
|
|
1246
|
-
[diagramEditorState, isReadOnly],
|
|
1247
|
-
);
|
|
1248
|
-
const [, dropConnector] = useDrop<ElementDragSource>(
|
|
1249
|
-
() => ({
|
|
1250
|
-
accept: CORE_DND_TYPE.PROJECT_EXPLORER_CLASS,
|
|
1251
|
-
drop: (item, monitor): void => handleDrop(item, monitor),
|
|
1252
|
-
}),
|
|
1253
|
-
[handleDrop],
|
|
1254
|
-
);
|
|
1255
|
-
dropConnector(ref);
|
|
1256
|
-
|
|
1257
|
-
return (
|
|
1258
|
-
<div
|
|
1259
|
-
ref={ref}
|
|
1260
|
-
className={clsx(
|
|
1261
|
-
'diagram-canvas diagram-editor__canvas',
|
|
1262
|
-
diagramEditorState.diagramCursorClass,
|
|
1263
|
-
)}
|
|
1264
|
-
data-testid={DSL_DIAGRAM_TEST_ID.DIAGRAM_EDITOR}
|
|
1265
|
-
tabIndex={0}
|
|
1266
|
-
/>
|
|
1267
|
-
);
|
|
1268
|
-
}),
|
|
1269
|
-
);
|
|
1270
|
-
|
|
1271
|
-
const DiagramEditorHeader = observer(
|
|
1272
|
-
(props: { diagramEditorState: DiagramEditorState }) => {
|
|
1273
|
-
const { diagramEditorState } = props;
|
|
1274
|
-
const createCenterZoomer =
|
|
1275
|
-
(zoomLevel: number): (() => void) =>
|
|
1276
|
-
(): void => {
|
|
1277
|
-
diagramEditorState.renderer.zoomCenter(zoomLevel / 100);
|
|
1278
|
-
};
|
|
1279
|
-
const zoomToFit = (): void => diagramEditorState.renderer.zoomToFit();
|
|
1280
|
-
|
|
1281
|
-
const toggleSidePanel = (): void => {
|
|
1282
|
-
diagramEditorState.sidePanelDisplayState.toggle();
|
|
1283
|
-
if (!diagramEditorState.sidePanelDisplayState.isOpen) {
|
|
1284
|
-
diagramEditorState.setSidePanelState(undefined);
|
|
1285
|
-
}
|
|
1286
|
-
};
|
|
1287
|
-
const isAlignerDisabled =
|
|
1288
|
-
diagramEditorState.renderer.selectedClasses.length < 2;
|
|
1289
|
-
|
|
1290
|
-
return (
|
|
1291
|
-
<>
|
|
1292
|
-
<div className="diagram-editor__header__group">
|
|
1293
|
-
<button
|
|
1294
|
-
className="diagram-editor__header__action diagram-editor__header__group__action"
|
|
1295
|
-
title="Align left"
|
|
1296
|
-
disabled={isAlignerDisabled}
|
|
1297
|
-
tabIndex={-1}
|
|
1298
|
-
onClick={(): void =>
|
|
1299
|
-
diagramEditorState.renderer.align(
|
|
1300
|
-
DIAGRAM_ALIGNER_OPERATOR.ALIGN_LEFT,
|
|
1301
|
-
)
|
|
1302
|
-
}
|
|
1303
|
-
>
|
|
1304
|
-
<AlignStartIcon className="diagram-editor__icon--aligner" />
|
|
1305
|
-
</button>
|
|
1306
|
-
<button
|
|
1307
|
-
className="diagram-editor__header__action diagram-editor__header__group__action"
|
|
1308
|
-
title="Align center"
|
|
1309
|
-
disabled={isAlignerDisabled}
|
|
1310
|
-
tabIndex={-1}
|
|
1311
|
-
onClick={(): void =>
|
|
1312
|
-
diagramEditorState.renderer.align(
|
|
1313
|
-
DIAGRAM_ALIGNER_OPERATOR.ALIGN_CENTER,
|
|
1314
|
-
)
|
|
1315
|
-
}
|
|
1316
|
-
>
|
|
1317
|
-
<AlignCenterIcon className="diagram-editor__icon--aligner" />
|
|
1318
|
-
</button>
|
|
1319
|
-
<button
|
|
1320
|
-
className="diagram-editor__header__action diagram-editor__header__group__action"
|
|
1321
|
-
title="Align right"
|
|
1322
|
-
disabled={isAlignerDisabled}
|
|
1323
|
-
tabIndex={-1}
|
|
1324
|
-
onClick={(): void =>
|
|
1325
|
-
diagramEditorState.renderer.align(
|
|
1326
|
-
DIAGRAM_ALIGNER_OPERATOR.ALIGN_RIGHT,
|
|
1327
|
-
)
|
|
1328
|
-
}
|
|
1329
|
-
>
|
|
1330
|
-
<AlignEndIcon className="diagram-editor__icon--aligner" />
|
|
1331
|
-
</button>
|
|
1332
|
-
</div>
|
|
1333
|
-
<div className="diagram-editor__header__group__separator" />
|
|
1334
|
-
<div className="diagram-editor__header__group">
|
|
1335
|
-
<button
|
|
1336
|
-
className="diagram-editor__header__action diagram-editor__header__group__action"
|
|
1337
|
-
title="Align top"
|
|
1338
|
-
disabled={isAlignerDisabled}
|
|
1339
|
-
tabIndex={-1}
|
|
1340
|
-
onClick={(): void =>
|
|
1341
|
-
diagramEditorState.renderer.align(
|
|
1342
|
-
DIAGRAM_ALIGNER_OPERATOR.ALIGN_TOP,
|
|
1343
|
-
)
|
|
1344
|
-
}
|
|
1345
|
-
>
|
|
1346
|
-
<AlignTopIcon className="diagram-editor__icon--aligner" />
|
|
1347
|
-
</button>
|
|
1348
|
-
<button
|
|
1349
|
-
className="diagram-editor__header__action diagram-editor__header__group__action"
|
|
1350
|
-
title="Align middle"
|
|
1351
|
-
disabled={isAlignerDisabled}
|
|
1352
|
-
tabIndex={-1}
|
|
1353
|
-
onClick={(): void =>
|
|
1354
|
-
diagramEditorState.renderer.align(
|
|
1355
|
-
DIAGRAM_ALIGNER_OPERATOR.ALIGN_MIDDLE,
|
|
1356
|
-
)
|
|
1357
|
-
}
|
|
1358
|
-
>
|
|
1359
|
-
<AlignMiddleIcon className="diagram-editor__icon--aligner" />
|
|
1360
|
-
</button>
|
|
1361
|
-
<button
|
|
1362
|
-
className="diagram-editor__header__action diagram-editor__header__group__action"
|
|
1363
|
-
title="Align bottom"
|
|
1364
|
-
disabled={isAlignerDisabled}
|
|
1365
|
-
tabIndex={-1}
|
|
1366
|
-
onClick={(): void =>
|
|
1367
|
-
diagramEditorState.renderer.align(
|
|
1368
|
-
DIAGRAM_ALIGNER_OPERATOR.ALIGN_BOTTOM,
|
|
1369
|
-
)
|
|
1370
|
-
}
|
|
1371
|
-
>
|
|
1372
|
-
<AlignBottomIcon className="diagram-editor__icon--aligner" />
|
|
1373
|
-
</button>
|
|
1374
|
-
</div>
|
|
1375
|
-
<div className="diagram-editor__header__group__separator" />
|
|
1376
|
-
<div className="diagram-editor__header__group">
|
|
1377
|
-
<button
|
|
1378
|
-
className="diagram-editor__header__action diagram-editor__header__group__action"
|
|
1379
|
-
title="Space horizontally"
|
|
1380
|
-
disabled={isAlignerDisabled}
|
|
1381
|
-
tabIndex={-1}
|
|
1382
|
-
onClick={(): void =>
|
|
1383
|
-
diagramEditorState.renderer.align(
|
|
1384
|
-
DIAGRAM_ALIGNER_OPERATOR.SPACE_HORIZONTALLY,
|
|
1385
|
-
)
|
|
1386
|
-
}
|
|
1387
|
-
>
|
|
1388
|
-
<DistributeHorizontalIcon className="diagram-editor__icon--aligner" />
|
|
1389
|
-
</button>
|
|
1390
|
-
<button
|
|
1391
|
-
className="diagram-editor__header__action diagram-editor__header__group__action"
|
|
1392
|
-
title="Space vertically"
|
|
1393
|
-
disabled={isAlignerDisabled}
|
|
1394
|
-
tabIndex={-1}
|
|
1395
|
-
onClick={(): void =>
|
|
1396
|
-
diagramEditorState.renderer.align(
|
|
1397
|
-
DIAGRAM_ALIGNER_OPERATOR.SPACE_VERTICALLY,
|
|
1398
|
-
)
|
|
1399
|
-
}
|
|
1400
|
-
>
|
|
1401
|
-
<DistributeVerticalIcon className="diagram-editor__icon--aligner" />
|
|
1402
|
-
</button>
|
|
1403
|
-
</div>
|
|
1404
|
-
<ControlledDropdownMenu
|
|
1405
|
-
className="diagram-editor__header__dropdown"
|
|
1406
|
-
title="Zoom..."
|
|
1407
|
-
content={
|
|
1408
|
-
<MenuContent>
|
|
1409
|
-
<MenuContentItem
|
|
1410
|
-
className="diagram-editor__header__zoomer__dropdown__menu__item"
|
|
1411
|
-
onClick={zoomToFit}
|
|
1412
|
-
>
|
|
1413
|
-
Fit
|
|
1414
|
-
</MenuContentItem>
|
|
1415
|
-
<MenuContentDivider />
|
|
1416
|
-
{DIAGRAM_ZOOM_LEVELS.map((zoomLevel) => (
|
|
1417
|
-
<MenuContentItem
|
|
1418
|
-
key={zoomLevel}
|
|
1419
|
-
className="diagram-editor__header__zoomer__dropdown__menu__item"
|
|
1420
|
-
onClick={createCenterZoomer(zoomLevel)}
|
|
1421
|
-
>
|
|
1422
|
-
{zoomLevel}%
|
|
1423
|
-
</MenuContentItem>
|
|
1424
|
-
))}
|
|
1425
|
-
</MenuContent>
|
|
1426
|
-
}
|
|
1427
|
-
menuProps={{
|
|
1428
|
-
anchorOrigin: { vertical: 'bottom', horizontal: 'right' },
|
|
1429
|
-
transformOrigin: { vertical: 'top', horizontal: 'right' },
|
|
1430
|
-
elevation: 7,
|
|
1431
|
-
}}
|
|
1432
|
-
>
|
|
1433
|
-
<div className="diagram-editor__header__dropdown__label diagram-editor__header__zoomer__dropdown__label">
|
|
1434
|
-
{Math.round(diagramEditorState.renderer.zoom * 100)}%
|
|
1435
|
-
</div>
|
|
1436
|
-
<div className="diagram-editor__header__dropdown__trigger diagram-editor__header__zoomer__dropdown__trigger">
|
|
1437
|
-
<CaretDownIcon />
|
|
1438
|
-
</div>
|
|
1439
|
-
</ControlledDropdownMenu>
|
|
1440
|
-
<div className="diagram-editor__header__actions">
|
|
1441
|
-
<button
|
|
1442
|
-
className={clsx('diagram-editor__header__action', {
|
|
1443
|
-
'diagram-editor__header__action--active':
|
|
1444
|
-
diagramEditorState.sidePanelDisplayState.isOpen,
|
|
1445
|
-
})}
|
|
1446
|
-
tabIndex={-1}
|
|
1447
|
-
onClick={toggleSidePanel}
|
|
1448
|
-
>
|
|
1449
|
-
<SidebarIcon className="diagram-editor__icon--sidebar" />
|
|
1450
|
-
</button>
|
|
1451
|
-
</div>
|
|
1452
|
-
</>
|
|
1453
|
-
);
|
|
1454
|
-
},
|
|
1455
|
-
);
|
|
1456
|
-
|
|
1457
|
-
export const DiagramEditor = observer(() => {
|
|
1458
|
-
const editorStore = useEditorStore();
|
|
1459
|
-
const diagramEditorState =
|
|
1460
|
-
editorStore.tabManagerState.getCurrentEditorState(DiagramEditorState);
|
|
1461
|
-
const diagramCanvasRef = useRef<HTMLDivElement>(null);
|
|
1462
|
-
const onContextMenuClose = (): void => diagramEditorState.closeContextMenu();
|
|
1463
|
-
|
|
1464
|
-
useApplicationNavigationContext(
|
|
1465
|
-
DSL_DIAGRAM_LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.DIAGRAM_EDITOR,
|
|
1466
|
-
);
|
|
1467
|
-
|
|
1468
|
-
useCommands(diagramEditorState);
|
|
1469
|
-
|
|
1470
|
-
return (
|
|
1471
|
-
<div className="diagram-editor">
|
|
1472
|
-
<div className="diagram-editor__header">
|
|
1473
|
-
{diagramEditorState.isDiagramRendererInitialized && (
|
|
1474
|
-
<DiagramEditorHeader diagramEditorState={diagramEditorState} />
|
|
1475
|
-
)}
|
|
1476
|
-
</div>
|
|
1477
|
-
<div className="diagram-editor__content">
|
|
1478
|
-
{diagramEditorState.isDiagramRendererInitialized && (
|
|
1479
|
-
<DiagramEditorOverlay diagramEditorState={diagramEditorState} />
|
|
1480
|
-
)}
|
|
1481
|
-
<ContextMenu
|
|
1482
|
-
className="diagram-editor__stage"
|
|
1483
|
-
content={
|
|
1484
|
-
<DiagramEditorContextMenu diagramEditorState={diagramEditorState} />
|
|
1485
|
-
}
|
|
1486
|
-
disabled={!diagramEditorState.showContextMenu}
|
|
1487
|
-
menuProps={{ elevation: 7 }}
|
|
1488
|
-
onClose={onContextMenuClose}
|
|
1489
|
-
>
|
|
1490
|
-
{diagramEditorState.isDiagramRendererInitialized && (
|
|
1491
|
-
<DiagramEditorToolPanel diagramEditorState={diagramEditorState} />
|
|
1492
|
-
)}
|
|
1493
|
-
<DiagramEditorDiagramCanvas
|
|
1494
|
-
diagramEditorState={diagramEditorState}
|
|
1495
|
-
ref={diagramCanvasRef}
|
|
1496
|
-
/>
|
|
1497
|
-
{diagramEditorState.isDiagramRendererInitialized && (
|
|
1498
|
-
<>
|
|
1499
|
-
<DiagramEditorInlinePropertyEditor
|
|
1500
|
-
diagramEditorState={diagramEditorState}
|
|
1501
|
-
/>
|
|
1502
|
-
<DiagramEditorInlineClassCreator
|
|
1503
|
-
diagramEditorState={diagramEditorState}
|
|
1504
|
-
/>
|
|
1505
|
-
<DiagramEditorInlineClassRenamer
|
|
1506
|
-
diagramEditorState={diagramEditorState}
|
|
1507
|
-
/>
|
|
1508
|
-
</>
|
|
1509
|
-
)}
|
|
1510
|
-
</ContextMenu>
|
|
1511
|
-
</div>
|
|
1512
|
-
</div>
|
|
1513
|
-
);
|
|
1514
|
-
});
|