@@ -23,9 +23,10 @@ namespace CSharpCodeAnalyst.GraphArea;
23
23
/// </summary>
24
24
internal class DependencyGraphViewer : IDependencyGraphViewer , IDependencyGraphBinding , INotifyPropertyChanged
25
25
{
26
- private readonly List < IContextCommand > _contextMenuCommands = [ ] ;
27
- private readonly List < IGlobalContextCommand > _globalContextMenuCommands = [ ] ;
26
+ private readonly List < IDependencyContextCommand > _edgeCommands = [ ] ;
27
+ private readonly List < IGlobalContextCommand > _globalCommands = [ ] ;
28
28
private readonly MsaglBuilder _msaglBuilder ;
29
+ private readonly List < ICodeElementContextCommand > _nodeCommands = [ ] ;
29
30
private readonly IPublisher _publisher ;
30
31
31
32
private IHighlighting _activeHighlighting = new EdgeHoveredHighlighting ( ) ;
@@ -86,14 +87,19 @@ public void AddToGraph(IEnumerable<CodeElement> originalCodeElements, IEnumerabl
86
87
RefreshGraph ( ) ;
87
88
}
88
89
89
- public void AddContextMenuCommand ( IContextCommand command )
90
+ public void AddContextMenuCommand ( ICodeElementContextCommand command )
90
91
{
91
- _contextMenuCommands . Add ( command ) ;
92
+ _nodeCommands . Add ( command ) ;
93
+ }
94
+
95
+ public void AddContextMenuCommand ( IDependencyContextCommand command )
96
+ {
97
+ _edgeCommands . Add ( command ) ;
92
98
}
93
99
94
100
public void AddGlobalContextMenuCommand ( IGlobalContextCommand command )
95
101
{
96
- _globalContextMenuCommands . Add ( command ) ;
102
+ _globalCommands . Add ( command ) ;
97
103
}
98
104
99
105
public void Layout ( )
@@ -126,7 +132,7 @@ public void SaveToSvg(FileStream stream)
126
132
127
133
public void SetHighlightMode ( HighlightMode valueMode )
128
134
{
129
- _activeHighlighting ? . Clear ( _msaglViewer ) ;
135
+ _activeHighlighting . Clear ( _msaglViewer ) ;
130
136
switch ( valueMode )
131
137
{
132
138
case HighlightMode . EdgeHovered :
@@ -166,7 +172,7 @@ public void ShowGlobalContextMenu()
166
172
. Select ( id => _clonedCodeGraph . Nodes [ id ] )
167
173
. ToList ( ) ;
168
174
169
- foreach ( var command in _globalContextMenuCommands )
175
+ foreach ( var command in _globalCommands )
170
176
{
171
177
if ( command . CanHandle ( markedElements ) is false )
172
178
{
@@ -201,6 +207,21 @@ public void Clear()
201
207
RefreshGraph ( ) ;
202
208
}
203
209
210
+ public void DeleteFromGraph ( List < Dependency > dependencies )
211
+ {
212
+ if ( _msaglViewer is null )
213
+ {
214
+ return ;
215
+ }
216
+
217
+ foreach ( var dependency in dependencies )
218
+ {
219
+ _clonedCodeGraph . Nodes [ dependency . SourceId ] . Dependencies . Remove ( dependency ) ;
220
+ }
221
+
222
+ RefreshGraph ( ) ;
223
+ }
224
+
204
225
public void DeleteFromGraph ( HashSet < string > idsToRemove )
205
226
{
206
227
if ( _msaglViewer is null )
@@ -390,59 +411,116 @@ bool IsCtrlPressed()
390
411
391
412
if ( e . RightButtonIsPressed )
392
413
{
393
- if ( _msaglViewer ? . ObjectUnderMouseCursor is not IViewerNode clickedObject )
414
+ if ( _msaglViewer ? . ObjectUnderMouseCursor is IViewerNode clickedObject )
394
415
{
395
- return ;
416
+ // Click on specific node
417
+ var node = clickedObject . Node ;
418
+ var contextMenu = new ContextMenu ( ) ;
419
+ var element = GetCodeElementFromUserData ( node ) ;
420
+ AddToContextMenuEntries ( element , contextMenu ) ;
421
+ if ( contextMenu . Items . Count > 0 )
422
+ {
423
+ contextMenu . IsOpen = true ;
424
+ }
425
+ }
426
+ else if ( _msaglViewer ? . ObjectUnderMouseCursor is IViewerEdge viewerEdge )
427
+ {
428
+ // Click on specific edge
429
+ var edge = viewerEdge . Edge ;
430
+ var contextMenu = new ContextMenu ( ) ;
431
+ var dependencies = GetDependenciesFromUserData ( edge ) ;
432
+ AddContextMenuEntries ( dependencies , contextMenu ) ;
433
+ if ( contextMenu . Items . Count > 0 )
434
+ {
435
+ contextMenu . IsOpen = true ;
436
+ }
437
+ }
438
+ else
439
+ {
440
+ // Click on free space
441
+ ShowGlobalContextMenu ( ) ;
396
442
}
397
-
398
- // Click on specific node
399
- var node = clickedObject . Node ;
400
- var contextMenu = new ContextMenu ( ) ;
401
-
402
- AddToContextMenuEntries ( node , contextMenu ) ;
403
-
404
- contextMenu . IsOpen = true ;
405
443
}
406
444
else
407
445
{
408
446
e . Handled = false ;
409
447
}
410
448
}
411
449
450
+ private void AddContextMenuEntries ( List < Dependency > dependencies , ContextMenu contextMenu )
451
+ {
452
+ if ( dependencies . Count == 0 )
453
+ {
454
+ return ;
455
+ }
456
+
457
+ foreach ( var cmd in _edgeCommands )
458
+ {
459
+ var menuItem = new MenuItem { Header = cmd . Label } ;
460
+ if ( cmd . CanHandle ( dependencies ) )
461
+ {
462
+ menuItem . Click += ( _ , _ ) => cmd . Invoke ( dependencies ) ;
463
+ contextMenu . Items . Add ( menuItem ) ;
464
+ }
465
+ }
466
+ }
467
+
468
+ private static List < Dependency > GetDependenciesFromUserData ( Edge edge )
469
+ {
470
+ var result = new List < Dependency > ( ) ;
471
+ switch ( edge . UserData )
472
+ {
473
+ case Dependency dependency :
474
+ result . Add ( dependency ) ;
475
+ break ;
476
+ case List < Dependency > dependencies :
477
+ result . AddRange ( dependencies ) ;
478
+ break ;
479
+ }
480
+
481
+ return result ;
482
+ }
483
+
484
+ private CodeElement ? GetCodeElementFromUserData ( Node node )
485
+ {
486
+ return node . UserData as CodeElement ;
487
+ }
412
488
413
489
/// <summary>
414
490
/// Commands registered for nodes
415
491
/// </summary>
416
- private void AddToContextMenuEntries ( Node node , ContextMenu contextMenu )
492
+ private void AddToContextMenuEntries ( CodeElement ? element , ContextMenu contextMenu )
417
493
{
494
+ if ( element is null )
495
+ {
496
+ return ;
497
+ }
498
+
418
499
var lastItemIsSeparator = true ;
419
500
420
- if ( node . UserData is CodeElement element )
501
+ foreach ( var cmd in _nodeCommands )
421
502
{
422
- foreach ( var cmd in _contextMenuCommands )
503
+ // Add separator command only if the last element was a real menu item.
504
+ if ( cmd is SeparatorCommand )
423
505
{
424
- // Add separator command only if the last element was a real menu item.
425
- if ( cmd is SeparatorCommand )
506
+ if ( lastItemIsSeparator is false )
426
507
{
427
- if ( lastItemIsSeparator is false )
428
- {
429
- contextMenu . Items . Add ( new Separator ( ) ) ;
430
- lastItemIsSeparator = true ;
431
- }
432
-
433
- continue ;
508
+ contextMenu . Items . Add ( new Separator ( ) ) ;
509
+ lastItemIsSeparator = true ;
434
510
}
435
511
436
- if ( ! cmd . CanHandle ( element ) )
437
- {
438
- continue ;
439
- }
512
+ continue ;
513
+ }
440
514
441
- var menuItem = new MenuItem { Header = cmd . Label } ;
442
- menuItem . Click += ( _ , _ ) => cmd . Invoke ( element ) ;
443
- contextMenu . Items . Add ( menuItem ) ;
444
- lastItemIsSeparator = false ;
515
+ if ( ! cmd . CanHandle ( element ) )
516
+ {
517
+ continue ;
445
518
}
519
+
520
+ var menuItem = new MenuItem { Header = cmd . Label } ;
521
+ menuItem . Click += ( _ , _ ) => cmd . Invoke ( element ) ;
522
+ contextMenu . Items . Add ( menuItem ) ;
523
+ lastItemIsSeparator = false ;
446
524
}
447
525
}
448
526
}
0 commit comments