1
- import * as React from 'react' ;
2
1
import { DiagramEngine , LinkWidget , PointModel } from '@projectstorm/react-diagrams-core' ;
2
+ import * as React from 'react' ;
3
+ import { MouseEvent , useEffect , useRef } from 'react' ;
3
4
import { DefaultLinkModel } from './DefaultLinkModel' ;
4
5
import { DefaultLinkPointWidget } from './DefaultLinkPointWidget' ;
5
6
import { DefaultLinkSegmentWidget } from './DefaultLinkSegmentWidget' ;
6
- import { MouseEvent } from 'react' ;
7
7
8
8
export interface DefaultLinkProps {
9
9
link : DefaultLinkModel ;
@@ -13,150 +13,120 @@ export interface DefaultLinkProps {
13
13
selected ?: ( event : MouseEvent ) => any ;
14
14
}
15
15
16
- export interface DefaultLinkState {
17
- selected : boolean ;
18
- }
16
+ export const DefaultLinkWidget : React . FC < DefaultLinkProps > = ( props ) => {
17
+ const [ selected , setSelected ] = React . useState ( false ) ;
18
+ const refPaths = useRef < React . RefObject < SVGPathElement > [ ] > ( [ ] ) ;
19
19
20
- export class DefaultLinkWidget extends React . Component < DefaultLinkProps , DefaultLinkState > {
21
- refPaths : React . RefObject < SVGPathElement > [ ] ;
20
+ const renderPoints = ( ) => {
21
+ return props . renderPoints ?? true ;
22
+ } ;
22
23
23
- constructor ( props : DefaultLinkProps ) {
24
- super ( props ) ;
25
- this . refPaths = [ ] ;
26
- this . state = {
27
- selected : false
24
+ useEffect ( ( ) => {
25
+ props . link . setRenderedPaths ( refPaths . current . map ( ( ref ) => ref . current ) . filter ( Boolean ) as SVGPathElement [ ] ) ;
26
+ return ( ) => {
27
+ props . link . setRenderedPaths ( [ ] ) ;
28
28
} ;
29
- }
30
-
31
- renderPoints ( ) {
32
- return this . props . renderPoints ?? true ;
33
- }
34
-
35
- componentDidUpdate ( ) : void {
36
- this . props . link . setRenderedPaths (
37
- this . refPaths . map ( ( ref ) => {
38
- return ref . current ;
39
- } )
40
- ) ;
41
- }
29
+ } , [ props . link ] ) ;
42
30
43
- componentDidMount ( ) : void {
44
- this . props . link . setRenderedPaths (
45
- this . refPaths . map ( ( ref ) => {
46
- return ref . current ;
47
- } )
48
- ) ;
49
- }
50
-
51
- componentWillUnmount ( ) : void {
52
- this . props . link . setRenderedPaths ( [ ] ) ;
53
- }
31
+ const generateRef = ( ) => {
32
+ const ref = React . createRef < SVGPathElement > ( ) ;
33
+ refPaths . current . push ( ref ) ;
34
+ return ref ;
35
+ } ;
54
36
55
- addPointToLink ( event : MouseEvent , index : number ) {
37
+ const addPointToLink = ( event : MouseEvent , index : number ) => {
56
38
if (
57
39
! event . shiftKey &&
58
- ! this . props . link . isLocked ( ) &&
59
- this . props . link . getPoints ( ) . length - 1 <= this . props . diagramEngine . getMaxNumberPointsPerLink ( )
40
+ ! props . link . isLocked ( ) &&
41
+ props . link . getPoints ( ) . length - 1 <= props . diagramEngine . getMaxNumberPointsPerLink ( )
60
42
) {
61
- const position = this . props . diagramEngine . getRelativeMousePoint ( event ) ;
62
- const point = this . props . link . point ( position . x , position . y , index ) ;
43
+ const position = props . diagramEngine . getRelativeMousePoint ( event ) ;
44
+ const point = props . link . point ( position . x , position . y , index ) ;
63
45
event . persist ( ) ;
64
46
event . stopPropagation ( ) ;
65
- this . forceUpdate ( ( ) => {
66
- this . props . diagramEngine . getActionEventBus ( ) . fireAction ( {
67
- event,
68
- model : point
69
- } ) ;
47
+ props . diagramEngine . getActionEventBus ( ) . fireAction ( {
48
+ event,
49
+ model : point
70
50
} ) ;
71
51
}
72
- }
52
+ } ;
73
53
74
- generatePoint ( point : PointModel ) : JSX . Element {
54
+ const generatePoint = ( point : PointModel ) : JSX . Element => {
75
55
return (
76
56
< DefaultLinkPointWidget
77
57
key = { point . getID ( ) }
78
58
point = { point as any }
79
- colorSelected = { this . props . link . getOptions ( ) . selectedColor }
80
- color = { this . props . link . getOptions ( ) . color }
59
+ colorSelected = { props . link . getOptions ( ) . selectedColor ?? '' }
60
+ color = { props . link . getOptions ( ) . color }
81
61
/>
82
62
) ;
83
- }
63
+ } ;
84
64
85
- generateLink ( path : string , extraProps : any , id : string | number ) : JSX . Element {
86
- const ref = React . createRef < SVGPathElement > ( ) ;
87
- this . refPaths . push ( ref ) ;
65
+ const generateLink = ( path : string , extraProps : any , id : string | number ) : JSX . Element => {
88
66
return (
89
67
< DefaultLinkSegmentWidget
90
68
key = { `link-${ id } ` }
91
69
path = { path }
92
- selected = { this . state . selected }
93
- diagramEngine = { this . props . diagramEngine }
94
- factory = { this . props . diagramEngine . getFactoryForLink ( this . props . link ) }
95
- link = { this . props . link }
96
- forwardRef = { ref }
97
- onSelection = { ( selected ) => {
98
- this . setState ( { selected : selected } ) ;
99
- } }
70
+ selected = { selected }
71
+ diagramEngine = { props . diagramEngine }
72
+ factory = { props . diagramEngine . getFactoryForLink ( props . link ) }
73
+ link = { props . link }
74
+ forwardRef = { generateRef ( ) }
75
+ onSelection = { setSelected }
100
76
extras = { extraProps }
101
77
/>
102
78
) ;
103
- }
104
-
105
- render ( ) {
106
- //ensure id is present for all points on the path
107
- var points = this . props . link . getPoints ( ) ;
108
- var paths = [ ] ;
109
- this . refPaths = [ ] ;
79
+ } ;
80
+
81
+ const points = props . link . getPoints ( ) ;
82
+ const paths = [ ] ;
83
+ refPaths . current = [ ] ; // Reset the refPaths for the current render
84
+
85
+ if ( points . length === 2 ) {
86
+ paths . push (
87
+ generateLink (
88
+ props . link . getSVGPath ( ) ,
89
+ {
90
+ onMouseDown : ( event : MouseEvent ) => {
91
+ props . selected ?.( event ) ;
92
+ addPointToLink ( event , 1 ) ;
93
+ }
94
+ } ,
95
+ '0'
96
+ )
97
+ ) ;
110
98
111
- if ( points . length === 2 ) {
99
+ if ( props . link . getTargetPort ( ) == null ) {
100
+ paths . push ( generatePoint ( points [ 1 ] ) ) ;
101
+ }
102
+ } else {
103
+ for ( let j = 0 ; j < points . length - 1 ; j ++ ) {
112
104
paths . push (
113
- this . generateLink (
114
- this . props . link . getSVGPath ( ) ,
105
+ generateLink (
106
+ LinkWidget . generateLinePath ( points [ j ] , points [ j + 1 ] ) ,
115
107
{
116
- onMouseDown : ( event ) => {
117
- this . props . selected ?.( event ) ;
118
- this . addPointToLink ( event , 1 ) ;
108
+ 'data-linkid' : props . link . getID ( ) ,
109
+ 'data-point' : j ,
110
+ onMouseDown : ( event : MouseEvent ) => {
111
+ props . selected ?.( event ) ;
112
+ addPointToLink ( event , j + 1 ) ;
119
113
}
120
114
} ,
121
- '0'
115
+ j
122
116
)
123
117
) ;
118
+ }
124
119
125
- // draw the link as dangeling
126
- if ( this . props . link . getTargetPort ( ) == null ) {
127
- paths . push ( this . generatePoint ( points [ 1 ] ) ) ;
128
- }
129
- } else {
130
- //draw the multiple anchors and complex line instead
131
- for ( let j = 0 ; j < points . length - 1 ; j ++ ) {
132
- paths . push (
133
- this . generateLink (
134
- LinkWidget . generateLinePath ( points [ j ] , points [ j + 1 ] ) ,
135
- {
136
- 'data-linkid' : this . props . link . getID ( ) ,
137
- 'data-point' : j ,
138
- onMouseDown : ( event : MouseEvent ) => {
139
- this . props . selected ?.( event ) ;
140
- this . addPointToLink ( event , j + 1 ) ;
141
- }
142
- } ,
143
- j
144
- )
145
- ) ;
120
+ if ( renderPoints ( ) ) {
121
+ for ( let i = 1 ; i < points . length - 1 ; i ++ ) {
122
+ paths . push ( generatePoint ( points [ i ] ) ) ;
146
123
}
147
124
148
- if ( this . renderPoints ( ) ) {
149
- //render the circles
150
- for ( let i = 1 ; i < points . length - 1 ; i ++ ) {
151
- paths . push ( this . generatePoint ( points [ i ] ) ) ;
152
- }
153
-
154
- if ( this . props . link . getTargetPort ( ) == null ) {
155
- paths . push ( this . generatePoint ( points [ points . length - 1 ] ) ) ;
156
- }
125
+ if ( props . link . getTargetPort ( ) == null ) {
126
+ paths . push ( generatePoint ( points [ points . length - 1 ] ) ) ;
157
127
}
158
128
}
159
-
160
- return < g data-default-link-test = { this . props . link . getOptions ( ) . testName } > { paths } </ g > ;
161
129
}
162
- }
130
+
131
+ return < g data-default-link-test = { props . link . getOptions ( ) . testName } > { paths } </ g > ;
132
+ } ;
0 commit comments