@@ -31,6 +31,63 @@ export class Editor {
3131 private _ctx :CanvasRenderingContext2D ;
3232 private mouseDrag = false ;
3333 private focusedChild :Node | undefined ;
34+
35+ /**
36+ * We are editing nodes inside of this node.
37+ * Undefined would be top-most nodes
38+ * It is an array to support recursive nesting, like folders in a computer
39+ */
40+ private weAreInsideOf :Node [ ] = [ ] ;
41+
42+ /**
43+ * The node in which we are inside of...
44+ */
45+ get contextNode ( ) {
46+ return this . weAreInsideOf . length ? this . weAreInsideOf [ this . weAreInsideOf . length - 1 ] : undefined ;
47+ }
48+
49+ enterNode ( node :Node ) {
50+ if ( node . canHanveChilds )
51+ {
52+ this . weAreInsideOf ?. push ( node ) ;
53+ this . refilterNodes ( ) ;
54+ }
55+ else
56+ {
57+ throw new Error ( `Node ${ node . nodeName } can't have childrens.` ) ;
58+ }
59+ }
60+
61+ exitCurrentNode ( ) {
62+ if ( this . contextNode )
63+ {
64+ this . weAreInsideOf . pop ( ) ;
65+ this . refilterNodes ( ) ;
66+ }
67+ }
68+
69+ /**
70+ * Return `true` only if the node is in context.
71+ */
72+ protected nodeIsInContext ( node :Node )
73+ {
74+ return this . contextNode == node . childOf ;
75+ }
76+
77+ protected get objsInContext ( ) {
78+ return this . objs . filter ( node => this . nodeIsInContext ( node ) ) ;
79+ }
80+
81+ protected refilterNodes ( ) {
82+
83+ }
84+
85+ /**
86+ * Used to know what node is under the mouse on click events....
87+ * Will be used to tell if a user double clicked a node or not....
88+ */
89+ private nodeUnderMouse :Node | undefined ;
90+
3491 private mouse :Vector2Like = { x :0 , y :0 }
3592 private aspectCorrection = 1 ;
3693 private canvasAspect :number ;
@@ -149,7 +206,7 @@ export class Editor {
149206 //
150207 // check if some prop wants to handle the wheel...
151208 //
152- for ( const obj of this . objs ) {
209+ for ( const obj of this . objsInContext ) {
153210 if ( mouseWheelCaptured ( obj , cursor , ev . deltaY ) )
154211 return ;
155212 // if( obj.traverse( elem=>{
@@ -181,6 +238,7 @@ export class Editor {
181238 canvas . addEventListener ( 'mousemove' , ( event ) => {
182239
183240 this . mouseMoved = true ;
241+ this . nodeUnderMouse = undefined ;
184242
185243 let scale = this . ctx . getTransform ( ) . a ; // Get the current scale (assuming uniform scaling)
186244 const mousePos = this . getMousePos ( event ) ;
@@ -276,7 +334,9 @@ export class Editor {
276334 //
277335 // let's see if some canvas element wants to capture the mouse....
278336 //
279- for ( const obj of this . zSortedObjs ) {
337+ for ( const obj of this . zSortedObjs ) {
338+
339+ if ( ! this . nodeIsInContext ( obj ) ) continue ;
280340
281341 //#region OUTLET
282342 //
@@ -334,6 +394,7 @@ export class Editor {
334394 {
335395 // default... will make the object move...
336396 this . focusedChild = obj ;
397+ this . nodeUnderMouse = obj ;
337398 this . bingToTop ( obj ) ;
338399
339400 break ; //<-- to avoid processing childrens under us....
@@ -542,6 +603,8 @@ export class Editor {
542603 }
543604
544605 node . editor = this ;
606+ node . childOf = this . contextNode ;
607+
545608 this . objs . push ( node ) ;
546609 this . zSortedObjs . unshift ( node ) ;
547610
@@ -723,7 +786,14 @@ export class Editor {
723786 let dotPos :Vector2Like | undefined ;
724787
725788 //#region draw connections
726- this . connections . forEach ( connection => {
789+ this . connections
790+
791+ //
792+ // this is enough since a connection can't point to a node in another context...
793+ //
794+ . filter ( connection => this . nodeIsInContext ( connection . from . owner ) )
795+
796+ . forEach ( connection => {
727797
728798 const from = this . global2canvas ( { x :connection . from . globalX , y :connection . from . globalY } ) ;
729799
@@ -978,7 +1048,7 @@ export class Editor {
9781048
9791049 const ctx = this . _ctx ;
9801050
981- this . objs . forEach ( node => {
1051+ this . objsInContext . forEach ( node => {
9821052
9831053 const objLeft = node . x ;
9841054 const objRight = node . x + node . width ( ctx ) ;
@@ -1011,6 +1081,11 @@ export class Editor {
10111081
10121082 this . zSortedObjs . forEach ( obj => {
10131083
1084+ //
1085+ // dont render if not enabled.
1086+ //
1087+ if ( ! this . nodeIsInContext ( obj ) ) return ;
1088+
10141089 ctx . save ( ) ;
10151090
10161091 obj . selected = this . selectedNodes . includes ( obj )
@@ -1030,7 +1105,17 @@ export class Editor {
10301105 requestAnimationFrame ( ( ) => this . start ( ) ) ;
10311106 }
10321107
1033- protected showNodeCreationMenu ( ev :MouseEvent ) {
1108+ protected showNodeCreationMenu ( ev :MouseEvent ) {
1109+
1110+ if ( this . nodeUnderMouse ) {
1111+
1112+ if ( this . nodeUnderMouse . canHanveChilds )
1113+ {
1114+ this . enterNode ( this . nodeUnderMouse )
1115+ }
1116+ return ;
1117+ } ;
1118+
10341119 const at = this . getCanvasMousePosition ( this . mouse ) ; ;
10351120
10361121 createNewNode ( ev . clientX , ev . clientY , newNode => {
0 commit comments