@@ -97,7 +97,7 @@ class Renderer {
9797 this . drawEdges ( ctx , edges , nodes ) ;
9898
9999 // Draw nodes
100- this . drawNodes ( ctx , nodes , selectedNodes ) ;
100+ this . drawNodes ( ctx , nodes , edges , selectedNodes ) ;
101101
102102 // Draw connection line
103103 if ( connecting ) {
@@ -164,11 +164,59 @@ class Renderer {
164164 } ) ;
165165 }
166166
167- drawNodes ( ctx , nodes , selectedNodes ) {
167+ drawPortIcon ( ctx , x , y , isInput ) {
168+ const offset = 5 ; // Distance from node border
169+ const arrowX = isInput ? x - offset : x + offset ;
170+
171+ ctx . beginPath ( ) ;
172+ if ( isInput ) {
173+ ctx . moveTo ( arrowX - 6 , y - 5 ) ;
174+ ctx . lineTo ( arrowX - 6 , y + 5 ) ;
175+ ctx . lineTo ( arrowX , y ) ;
176+ } else {
177+ ctx . moveTo ( arrowX , y - 5 ) ;
178+ ctx . lineTo ( arrowX , y + 5 ) ;
179+ ctx . lineTo ( arrowX + 6 , y ) ;
180+ }
181+ ctx . closePath ( ) ;
182+ ctx . strokeStyle = '#999999' ;
183+ ctx . lineWidth = 1 ;
184+ ctx . stroke ( ) ;
185+ }
186+
187+ drawLabelArrow ( ctx , x , y , isControl ) {
188+ if ( isControl ) {
189+ const lineLength = 10 ;
190+
191+ // Draw line
192+ ctx . beginPath ( ) ;
193+ ctx . moveTo ( x , y ) ;
194+ ctx . lineTo ( x + lineLength , y ) ;
195+ ctx . strokeStyle = '#4CAF50' ;
196+ ctx . lineWidth = 2 ;
197+ ctx . stroke ( ) ;
198+
199+ // Draw arrow
200+ ctx . beginPath ( ) ;
201+ ctx . moveTo ( x + lineLength , y - 5 ) ;
202+ ctx . lineTo ( x + lineLength , y + 5 ) ;
203+ ctx . lineTo ( x + lineLength + 6 , y ) ;
204+ ctx . closePath ( ) ;
205+ ctx . fillStyle = '#4CAF50' ;
206+ ctx . fill ( ) ;
207+ } else {
208+ // Draw orange circle for data ports
209+ ctx . beginPath ( ) ;
210+ ctx . arc ( x + 5 , y , 4 , 0 , Math . PI * 2 ) ;
211+ ctx . fillStyle = '#FFA500' ;
212+ ctx . fill ( ) ;
213+ }
214+ }
215+
216+ drawNodes ( ctx , nodes , edges , selectedNodes ) {
168217 nodes . forEach ( node => {
169218 const { width, height } = this . getNodeDimensions ( node , ctx ) ;
170219
171- // Skip nodes that are completely outside the view
172220 if ( ! this . isRectInView ( node . x , node . y , width , height , ctx . canvas . width , ctx . canvas . height ) ) {
173221 return ;
174222 }
@@ -220,22 +268,44 @@ class Renderer {
220268
221269 // Input ports
222270 nodeType . inputs . forEach ( ( input , i ) => {
223- ctx . fillStyle = '#FFA500' ;
224- ctx . beginPath ( ) ;
225- ctx . arc ( node . x , node . y + currentHeight + i * 20 , 5 , 0 , 2 * Math . PI ) ;
226- ctx . fill ( ) ;
271+ const portY = node . y + currentHeight + i * 20 ;
272+ const isControl = input . type === 'control' ;
273+
274+ // Check if port is connected
275+ const isPortConnected = edges . some ( edge =>
276+ edge . end . nodeId === node . id &&
277+ edge . end . index === i &&
278+ edge . end . isInput
279+ ) ;
280+
281+ if ( ! isPortConnected ) {
282+ this . drawPortIcon ( ctx , node . x , portY , true ) ;
283+ }
284+
285+ this . drawLabelArrow ( ctx , node . x + 15 , portY , isControl ) ;
227286 ctx . fillStyle = 'white' ;
228- ctx . fillText ( ` ${ input . type === 'control' ? '▶' : '●' } ${ input . name } ` , node . x + 10 , node . y + currentHeight + 5 + i * 20 ) ;
287+ ctx . fillText ( input . name , node . x + 35 , portY + 5 ) ;
229288 } ) ;
230289
231290 // Output ports
232291 nodeType . outputs . forEach ( ( output , i ) => {
233- ctx . fillStyle = '#FFA500' ;
234- ctx . beginPath ( ) ;
235- ctx . arc ( node . x + width , node . y + currentHeight + i * 20 , 5 , 0 , 2 * Math . PI ) ;
236- ctx . fill ( ) ;
292+ const portY = node . y + currentHeight + i * 20 ;
293+ const isControl = output . type === 'control' ;
294+
295+ const isPortConnected = edges . some ( edge =>
296+ edge . start . nodeId === node . id &&
297+ edge . start . index === i &&
298+ ! edge . start . isInput
299+ ) ;
300+
301+ if ( ! isPortConnected ) {
302+ this . drawPortIcon ( ctx , node . x + width , portY , false ) ;
303+ }
304+
237305 ctx . fillStyle = 'white' ;
238- ctx . fillText ( `${ output . name } ${ output . type === 'control' ? '▶' : '●' } ` , node . x + width - 70 , node . y + currentHeight + 5 + i * 20 ) ;
306+ const textWidth = ctx . measureText ( output . name ) . width ;
307+ ctx . fillText ( output . name , node . x + width - textWidth - 35 , portY + 5 ) ;
308+ this . drawLabelArrow ( ctx , node . x + width - 25 , portY , isControl ) ;
239309 } ) ;
240310
241311 currentHeight += Math . max ( nodeType . inputs . length , nodeType . outputs . length ) * 15 ;
0 commit comments