@@ -14,6 +14,8 @@ import { promptNewStateName } from "../utils/PromptNewStateName";
1414import { PossibleTransitionValues } from "../consts/PossibleTransitionValues" ;
1515import { StateNameMaxLength } from "../consts/StateNameMaxLength" ;
1616import { PlaygroundSize } from "./interfaces/playgroundSize" ;
17+ import { StyledTransitionLabel } from "../features/components/playground/StyledTransitionLabel" ;
18+ import { MaxNumberOfStates } from "../consts/MaxNumberOfStates" ;
1719
1820const Editor = ( ) => {
1921 console . log ( "re rendering Editor" ) ;
@@ -97,6 +99,10 @@ const Editor = () => {
9799 const [ size , setSize ] = useState < PlaygroundSize > ( { width : 0 , height : 0 } ) ;
98100
99101 const handleAddRow = ( row : RowModel ) => {
102+ if ( boxes . length >= MaxNumberOfStates ) {
103+ alert ( `Maximum ${ MaxNumberOfStates } states allowed` ) ;
104+ return ;
105+ }
100106 setGridData ( ( prev ) => [ ...prev , row ] ) ;
101107 setGridRowId ( ( prev ) => prev + 1 ) ;
102108 console . log (
@@ -178,28 +184,54 @@ const Editor = () => {
178184 return ;
179185 }
180186
181- const previousRow = gridData . find ( ( r ) => r . id === row . id ) ;
187+ const oldRow = gridData . find ( ( r ) => r . id === row . id ) ;
188+ if ( ! oldRow ) {
189+ alert ( "Cannot save row." ) ;
190+ return ;
191+ }
192+
182193 if ( row . node . length > StateNameMaxLength ) {
183194 alert ( `State name cannot be more than ${ StateNameMaxLength } characters.` ) ;
184- if ( previousRow ) {
185- setGridData ( ( prev ) =>
186- prev . map ( ( r ) => ( r . id === row . id ? previousRow : r ) )
187- ) ;
195+ if ( oldRow ) {
196+ setGridData ( ( prev ) => prev . map ( ( r ) => ( r . id === row . id ? oldRow : r ) ) ) ;
197+ }
198+ return ;
199+ }
200+
201+ // if state name is changed AND transition values are added/updated/removed, not allowed
202+ if (
203+ oldRow . node !== row . node &&
204+ PossibleTransitionValues . some (
205+ ( key ) =>
206+ row [ key === "^" ? "nul" : key ] !== oldRow [ key === "^" ? "nul" : key ]
207+ )
208+ ) {
209+ alert (
210+ `Cannot change state name when transition values are added/updated/removed.`
211+ ) ;
212+ if ( oldRow ) {
213+ setGridData ( ( prev ) => prev . map ( ( r ) => ( r . id === row . id ? oldRow : r ) ) ) ;
188214 }
189215 return ;
190216 }
191217
218+ const nulPossibleTransitionValues = PossibleTransitionValues . map ( ( v ) =>
219+ v === "^" ? "nul" : v
220+ ) ;
221+ let updatedGridData : RowModel [ ] = [ ] ;
222+ let errorWhileSavingRow = false ;
192223 setGridData ( ( prev ) => {
193224 console . log ( "handleSaveRow prev" , prev ) ;
194225 let availableNodeValues = prev . map ( ( r ) => r . node ) . filter ( ( v ) => v !== "" ) ;
226+ // if (oldRow.node !== row.node)
227+ // availableNodeValues = availableNodeValues
228+ // .filter((v) => v !== oldRow.node)
229+ // .concat(row.node);
230+
195231 if ( ! availableNodeValues . includes ( row . node ) )
196232 availableNodeValues . push ( row . node ) ;
197-
198233 console . log ( "availableNodeValues" , availableNodeValues ) ;
199234
200- const nulPossibleTransitionValues = PossibleTransitionValues . map ( ( v ) =>
201- v === "^" ? "nul" : v
202- ) ;
203235 const areTransitionValuesInvalid = nulPossibleTransitionValues . some (
204236 ( key ) => {
205237 const transitionValues = row [ key ]
@@ -217,22 +249,24 @@ const Editor = () => {
217249 ", "
218250 ) } `
219251 ) ;
220- return prev ;
252+ errorWhileSavingRow = true ;
253+ return prev . map ( ( r ) => ( r . id === row . id ? oldRow : r ) ) ;
221254 }
222255
223- const nodeAlreadyExists = prev . find (
256+ const stateAlreadyExists = prev . find (
224257 ( r ) =>
225258 r . node === row . node &&
226259 r . a === row . a &&
227260 r . b === row . b &&
228261 r . nul === row . nul
229262 ) ;
230- if ( nodeAlreadyExists ) {
263+ if ( stateAlreadyExists ) {
231264 alert ( "This state value already exists. Kindly choose another value." ) ;
265+ errorWhileSavingRow = true ;
232266 return prev ;
233267 }
234268
235- return prev . map ( ( r ) =>
269+ updatedGridData = prev . map ( ( r ) =>
236270 r . id === row . id
237271 ? {
238272 ...r ,
@@ -242,10 +276,10 @@ const Editor = () => {
242276 key === "^" ? "nul" : key ,
243277 row [ key === "^" ? "nul" : key ]
244278 . toString ( )
245- . includes ( previousRow . node )
279+ . includes ( oldRow . node )
246280 ? row [ key === "^" ? "nul" : key ]
247281 . toString ( )
248- . replace ( previousRow . node , row . node )
282+ . replace ( oldRow . node , row . node )
249283 : row [ key === "^" ? "nul" : key ] ,
250284 ] )
251285 ) ,
@@ -255,41 +289,232 @@ const Editor = () => {
255289 ...Object . fromEntries (
256290 PossibleTransitionValues . map ( ( key ) => [
257291 key === "^" ? "nul" : key ,
258- r [ key === "^" ? "nul" : key ]
259- . toString ( )
260- . includes ( previousRow . node )
292+ r [ key === "^" ? "nul" : key ] . toString ( ) . includes ( oldRow . node )
261293 ? r [ key === "^" ? "nul" : key ]
262294 . toString ( )
263- . replace ( previousRow . node , row . node )
295+ . replace ( oldRow . node , row . node )
264296 : r [ key === "^" ? "nul" : key ] ,
265297 ] )
266298 ) ,
267299 }
268300 ) ;
301+
302+ return updatedGridData ;
269303 } ) ;
270304
271- setBoxes ( ( prev ) =>
272- prev . map ( ( b ) => ( b . id === previousRow . node ? { ...b , id : row . node } : b ) )
273- ) ;
305+ if ( ! errorWhileSavingRow ) {
306+ setBoxes ( ( prev ) =>
307+ prev . map ( ( b ) => ( b . id === oldRow . node ? { ...b , id : row . node } : b ) )
308+ ) ;
274309
275- setLines ( ( prev ) =>
276- prev . map ( ( l ) =>
277- l . props . start === previousRow . node && l . props . end === previousRow . node
278- ? {
279- ...l ,
280- props : {
281- ...l . props ,
282- start : row . node ,
283- end : row . node ,
284- } ,
310+ // if only state name is changed
311+ if (
312+ oldRow . node !== row . node &&
313+ PossibleTransitionValues . every (
314+ ( key ) =>
315+ row [ key === "^" ? "nul" : key ] === oldRow [ key === "^" ? "nul" : key ]
316+ )
317+ ) {
318+ let updatedtransitions = lines . map ( ( l ) =>
319+ l . props . start === oldRow . node && l . props . end === oldRow . node
320+ ? {
321+ ...l ,
322+ props : {
323+ ...l . props ,
324+ start : row . node ,
325+ end : row . node ,
326+ } ,
327+ }
328+ : l . props . start === oldRow . node
329+ ? {
330+ ...l ,
331+ props : {
332+ ...l . props ,
333+ start : row . node ,
334+ } ,
335+ }
336+ : l . props . end === oldRow . node
337+ ? {
338+ ...l ,
339+ props : {
340+ ...l . props ,
341+ end : row . node ,
342+ } ,
343+ }
344+ : l
345+ ) ;
346+ console . log ( "updatedtransitions" , updatedtransitions ) ;
347+ setLines ( updatedtransitions ) ;
348+ } else {
349+ // if new transitions are added
350+
351+ let addedTransitions : TransitionModel [ ] = [ ] ;
352+ let removedTransitions : TransitionModel [ ] = [ ] ;
353+
354+ PossibleTransitionValues . forEach ( ( key ) => {
355+ const oldTransitionValues = oldRow [ key === "^" ? "nul" : key ]
356+ . toString ( )
357+ . split ( " " )
358+ . filter ( ( v ) => v !== "" ) ;
359+ console . log ( "oldTransitionValues" , oldTransitionValues ) ;
360+
361+ const newTransitionValues = row [ key === "^" ? "nul" : key ]
362+ . toString ( )
363+ . split ( " " )
364+ . filter ( ( v ) => v !== "" ) ;
365+ console . log ( "newTransitionValues" , newTransitionValues ) ;
366+
367+ const addedTransitionValues = newTransitionValues . filter (
368+ ( v ) => ! oldTransitionValues . includes ( v )
369+ ) ;
370+ console . log ( "addedTransitionValues" , addedTransitionValues ) ;
371+
372+ const removedTransitionValues = oldTransitionValues . filter (
373+ ( v ) => ! newTransitionValues . includes ( v )
374+ ) ;
375+ console . log ( "removedTransitionValues" , removedTransitionValues ) ;
376+
377+ addedTransitionValues . forEach ( ( v ) => {
378+ console . log ( "addedTransitionValues key, v: " , key , v ) ;
379+
380+ // if transition value v is already present in the transitions array, then just update it's labels & value
381+ const transitionAlreadyExists = addedTransitions . find (
382+ ( t ) => t . props . start === row . node && t . props . end === v
383+ ) ;
384+
385+ if ( transitionAlreadyExists ) {
386+ transitionAlreadyExists . props . labels = (
387+ < StyledTransitionLabel
388+ label = { transitionAlreadyExists . props . value + key }
389+ />
390+ ) ;
391+ transitionAlreadyExists . props . value =
392+ transitionAlreadyExists . props . value + key ;
393+ } else {
394+ const isSelfTransition = v === row . node ;
395+ const newLine : TransitionModel = {
396+ props : {
397+ start : row . node ,
398+ end : v ,
399+ labels : < StyledTransitionLabel label = { key } /> ,
400+ value : key ,
401+ animateDrawing : true ,
402+ _extendSVGcanvas : isSelfTransition ? 25 : 0 ,
403+ _cpx1Offset : isSelfTransition ? - 50 : 0 ,
404+ _cpy1Offset : isSelfTransition ? - 50 : 0 ,
405+ _cpx2Offset : isSelfTransition ? 50 : 0 ,
406+ _cpy2Offset : isSelfTransition ? - 50 : 0 ,
407+ } ,
408+ menuWindowOpened : false ,
409+ } ;
410+ addedTransitions . push ( newLine ) ;
285411 }
286- : l . props . start === previousRow . node
287- ? { ...l , props : { ...l . props , start : row . node } }
288- : l . props . end === previousRow . node
289- ? { ...l , props : { ...l . props , end : row . node } }
290- : l
291- )
292- ) ;
412+ } ) ;
413+ console . log ( "addedTransitions" , addedTransitions ) ;
414+
415+ removedTransitionValues . forEach ( ( v ) => {
416+ console . log ( "removedTransitionValues key, v: " , key , v ) ;
417+ const removedTransition = lines . find (
418+ ( l ) => l . props . start === row . node && l . props . end === v
419+ ) ;
420+
421+ // if removed transition's label (value) is of length 1, then remove the transition
422+ if ( removedTransition . props . value . length === 1 ) {
423+ removedTransitions . push ( removedTransition ) ;
424+ } else {
425+ // else just update the transition's label & value
426+ removedTransition . props . labels = (
427+ < StyledTransitionLabel
428+ label = { removedTransition . props . value . replace ( key , "" ) }
429+ />
430+ ) ;
431+ removedTransition . props . value =
432+ removedTransition . props . value . replace ( key , "" ) ;
433+ }
434+ } ) ;
435+ console . log ( "removedTransitions" , removedTransitions ) ;
436+ } ) ;
437+
438+ setLines ( ( prev ) => {
439+ // update removedTransitions's labels && value if it's already present
440+ const updatedRemovedTransitions = prev . map ( ( l ) =>
441+ removedTransitions . find (
442+ ( t ) => t . props . start === l . props . start && t . props . end === l . props . end
443+ )
444+ ? {
445+ ...l ,
446+ props : {
447+ ...l . props ,
448+ labels : (
449+ < StyledTransitionLabel
450+ label = {
451+ removedTransitions . find (
452+ ( t ) =>
453+ t . props . start === l . props . start &&
454+ t . props . end === l . props . end
455+ ) ?. props . value
456+ }
457+ />
458+ ) ,
459+ value :
460+ removedTransitions . find (
461+ ( t ) =>
462+ t . props . start === l . props . start &&
463+ t . props . end === l . props . end
464+ ) ?. props . value ,
465+ } ,
466+ }
467+ : l
468+ ) ;
469+
470+
471+ // const updatedRemovedTransitions = prev.filter(
472+ // (l) =>
473+ // !removedTransitions.find(
474+ // (r) =>
475+ // r.props.start === l.props.start && r.props.end === l.props.end
476+ // )
477+ // );
478+ console . log ( "updatedRemovedTransitions" , updatedRemovedTransitions ) ;
479+
480+ // update addedTransitions's labels & value if it's are already present
481+ const updatedAddedTransitions = addedTransitions . map ( ( a ) => {
482+ const transitionAlreadyExists = prev . find (
483+ ( p ) =>
484+ p . props . start === a . props . start && p . props . end === a . props . end
485+ ) ;
486+ console . log (
487+ "transitionAlreadyExists.props.value, a.props.value:" ,
488+ transitionAlreadyExists ?. props . value ,
489+ a . props . value
490+ ) ;
491+ if (
492+ transitionAlreadyExists &&
493+ transitionAlreadyExists . props . value !== a . props . value
494+ ) {
495+ return {
496+ ...transitionAlreadyExists ,
497+ props : {
498+ ...transitionAlreadyExists . props ,
499+ labels : (
500+ < StyledTransitionLabel
501+ label = {
502+ transitionAlreadyExists . props . value + a . props . value
503+ }
504+ />
505+ ) ,
506+ value : transitionAlreadyExists . props . value + a . props . value ,
507+ } ,
508+ } ;
509+ }
510+ return a ;
511+ } ) ;
512+ console . log ( "updatedAddedTransitions" , updatedAddedTransitions ) ;
513+
514+ return [ ...updatedRemovedTransitions , ...updatedAddedTransitions ] ;
515+ } ) ;
516+ }
517+ }
293518 } ;
294519
295520 const toggleInitialState = ( row : RowModel ) => {
@@ -367,8 +592,11 @@ const Editor = () => {
367592
368593 const handleDropDynamic = ( e : any ) => {
369594 console . log ( "handleDropDynamic" , e ) ;
370- // let l = boxes.length;
371- // while (checkExsitence("q" + l)) l++;
595+ if ( boxes . length >= MaxNumberOfStates ) {
596+ alert ( `Maximum ${ MaxNumberOfStates } states allowed.` ) ;
597+ return ;
598+ }
599+
372600 let { x, y } = e . target . getBoundingClientRect ( ) ;
373601 const stateName = promptNewStateName ( boxes , `q${ gridRowId } ` ) ;
374602 if ( stateName ) {
0 commit comments