34
34
35
35
namespace Graph
36
36
{
37
+ public delegate bool AcceptElement ( IElement element ) ;
38
+
37
39
public partial class GraphControl : Control
38
40
{
39
41
#region Constructor
@@ -49,11 +51,30 @@ public GraphControl()
49
51
public event EventHandler < AcceptNodeEventArgs > NodeAdded ;
50
52
public event EventHandler < AcceptNodeEventArgs > NodeRemoving ;
51
53
public event EventHandler < NodeEventArgs > NodeRemoved ;
54
+ public event EventHandler < AcceptElementLocationEventArgs > ShowElementMenu ;
52
55
public event EventHandler < AcceptNodeConnectionEventArgs > ConnectionAdding ;
53
56
public event EventHandler < AcceptNodeConnectionEventArgs > ConnectionAdded ;
54
57
public event EventHandler < AcceptNodeConnectionEventArgs > ConnectionRemoving ;
55
58
public event EventHandler < NodeConnectionEventArgs > ConnectionRemoved ;
56
59
60
+ #region Grid
61
+ public bool ShowGrid = true ;
62
+ public float GridStep = 16.0f ;
63
+ private Color internalGridColor = Color . LightGray ;
64
+ private Pen GridPen = new Pen ( Color . LightGray ) ;
65
+ public Color GridColor
66
+ {
67
+ get { return internalGridColor ; }
68
+ set
69
+ {
70
+ if ( internalGridColor == value )
71
+ return ;
72
+
73
+ internalGridColor = value ;
74
+ GridPen = new Pen ( internalGridColor ) ;
75
+ }
76
+ }
77
+ #endregion
57
78
58
79
#region DragElement
59
80
IElement internalDragElement ;
@@ -762,6 +783,62 @@ IElement FindElementAt(PointF location)
762
783
}
763
784
#endregion
764
785
786
+ #region FindElementAt
787
+ IElement FindElementAt ( PointF location , AcceptElement acceptElement )
788
+ {
789
+ foreach ( var node in graphNodes )
790
+ {
791
+ var inputConnector = FindInputConnectorAt ( node , location ) ;
792
+ if ( inputConnector != null && acceptElement ( inputConnector ) )
793
+ return inputConnector ;
794
+
795
+ var outputConnector = FindOutputConnectorAt ( node , location ) ;
796
+ if ( outputConnector != null && acceptElement ( outputConnector ) )
797
+ return outputConnector ;
798
+
799
+ if ( node . bounds . Contains ( location ) )
800
+ {
801
+ var item = FindNodeItemAt ( node , location ) ;
802
+ if ( item != null && acceptElement ( item ) )
803
+ return item ;
804
+ if ( acceptElement ( node ) )
805
+ return node ;
806
+ else
807
+ return null ;
808
+ }
809
+ }
810
+
811
+ var skipConnections = new HashSet < NodeConnection > ( ) ;
812
+ var foundConnections = new List < NodeConnection > ( ) ;
813
+ foreach ( var node in graphNodes )
814
+ {
815
+ foreach ( var connection in node . connections )
816
+ {
817
+ if ( skipConnections . Add ( connection ) ) // if we can add it, we haven't checked it yet
818
+ {
819
+ if ( connection . bounds . Contains ( location ) )
820
+ foundConnections . Insert ( 0 , connection ) ;
821
+ }
822
+ }
823
+ }
824
+ foreach ( var connection in foundConnections )
825
+ {
826
+ if ( connection . textBounds . Contains ( location ) && acceptElement ( connection ) )
827
+ return connection ;
828
+ }
829
+ foreach ( var connection in foundConnections )
830
+ {
831
+ using ( var region = GraphRenderer . GetConnectionRegion ( connection ) )
832
+ {
833
+ if ( region . IsVisible ( location ) && acceptElement ( connection ) )
834
+ return connection ;
835
+ }
836
+ }
837
+
838
+ return null ;
839
+ }
840
+ #endregion
841
+
765
842
#region GetTransformedLocation
766
843
PointF GetTransformedLocation ( )
767
844
{
@@ -800,23 +877,24 @@ protected override void OnPaint(PaintEventArgs e)
800
877
801
878
if ( e . Graphics == null )
802
879
return ;
880
+
803
881
804
- e . Graphics . Clear ( Color . White ) ;
805
-
806
- if ( this . graphNodes . Count == 0 )
807
- return ;
808
-
809
- UpdateMatrices ( ) ;
810
- e . Graphics . PageUnit = GraphicsUnit . Pixel ;
882
+ e . Graphics . PageUnit = GraphicsUnit . Pixel ;
811
883
e . Graphics . CompositingQuality = CompositingQuality . GammaCorrected ;
812
- e . Graphics . InterpolationMode = InterpolationMode . HighQualityBicubic ;
813
- e . Graphics . SmoothingMode = SmoothingMode . HighQuality ;
814
884
e . Graphics . TextRenderingHint = TextRenderingHint . ClearTypeGridFit ;
815
885
e . Graphics . PixelOffsetMode = PixelOffsetMode . HighQuality ;
816
-
817
-
886
+ e . Graphics . InterpolationMode = InterpolationMode . HighQualityBicubic ;
887
+
888
+ UpdateMatrices ( ) ;
818
889
e . Graphics . Transform = transformation ;
819
890
891
+ OnDrawBackground ( e ) ;
892
+
893
+ e . Graphics . SmoothingMode = SmoothingMode . HighQuality ;
894
+
895
+ if ( this . graphNodes . Count == 0 )
896
+ return ;
897
+
820
898
821
899
var transformed_location = GetTransformedLocation ( ) ;
822
900
if ( command == CommandMode . MarqueSelection )
@@ -857,6 +935,41 @@ protected override void OnPaint(PaintEventArgs e)
857
935
}
858
936
#endregion
859
937
938
+ #region OnDrawBackground
939
+ virtual protected void OnDrawBackground ( PaintEventArgs e )
940
+ {
941
+ e . Graphics . Clear ( Color . White ) ;
942
+
943
+ if ( ! ShowGrid )
944
+ return ;
945
+
946
+ var points = new PointF [ ] {
947
+ new PointF ( e . ClipRectangle . Left , e . ClipRectangle . Top ) ,
948
+ new PointF ( e . ClipRectangle . Right , e . ClipRectangle . Bottom )
949
+ } ;
950
+
951
+ inverse_transformation . TransformPoints ( points ) ;
952
+
953
+ var left = points [ 0 ] . X ;
954
+ var right = points [ 1 ] . X ;
955
+ var top = points [ 0 ] . Y ;
956
+ var bottom = points [ 1 ] . Y ;
957
+ var stepScaled = GridStep ;
958
+
959
+ var xOffset = ( ( float ) Math . Round ( left / stepScaled ) * stepScaled ) ;
960
+ var yOffset = ( ( float ) Math . Round ( top / stepScaled ) * stepScaled ) ;
961
+
962
+ if ( stepScaled > 3 )
963
+ {
964
+ for ( float x = xOffset ; x < right ; x += stepScaled )
965
+ e . Graphics . DrawLine ( GridPen , x , top , x , bottom ) ;
966
+
967
+ for ( float y = yOffset ; y < bottom ; y += stepScaled )
968
+ e . Graphics . DrawLine ( GridPen , left , y , right , y ) ;
969
+ }
970
+ }
971
+ #endregion
972
+
860
973
861
974
862
975
#region OnMouseWheel
@@ -1436,7 +1549,7 @@ private bool ConnectionIsAllowed(NodeConnector from, NodeConnector to)
1436
1549
if ( ! CompatibilityStrategy . CanConnect ( from , to ) )
1437
1550
return false ;
1438
1551
}
1439
-
1552
+
1440
1553
// If someone has subscribed to the ConnectionAdding event,
1441
1554
// give them a chance to interrupt this connection attempt.
1442
1555
if ( null != ConnectionAdding )
@@ -1663,8 +1776,8 @@ protected override void OnDoubleClick(EventArgs e)
1663
1776
}
1664
1777
#endregion
1665
1778
1666
- #region OnClick
1667
- protected override void OnClick ( EventArgs e )
1779
+ #region OnMouseClick
1780
+ protected override void OnMouseClick ( MouseEventArgs e )
1668
1781
{
1669
1782
try
1670
1783
{
@@ -1676,6 +1789,31 @@ protected override void OnClick(EventArgs e)
1676
1789
inverse_transformation . TransformPoints ( points ) ;
1677
1790
var transformed_location = points [ 0 ] ;
1678
1791
1792
+ if ( e . Button == MouseButtons . Right )
1793
+ {
1794
+ if ( null != ShowElementMenu )
1795
+ {
1796
+ // See if we clicked on an element and give our owner the chance to show a menu
1797
+ var result = FindElementAt ( transformed_location , delegate ( IElement el )
1798
+ {
1799
+ // Fire the event and see if someone cancels it.
1800
+ var eventArgs = new AcceptElementLocationEventArgs ( el , this . PointToScreen ( lastLocation ) ) ;
1801
+ // Give our owner the chance to show a menu for this element ...
1802
+ ShowElementMenu ( this , eventArgs ) ;
1803
+ // If the owner declines (cancel == true) then we'll continue looking up the hierarchy ..
1804
+ return ! eventArgs . Cancel ;
1805
+ } ) ;
1806
+ // If we haven't found anything to click on we'll just return the event with a null pointer ..
1807
+ // allowing our owner to show a generic menu
1808
+ if ( result == null )
1809
+ {
1810
+ var eventArgs = new AcceptElementLocationEventArgs ( null , this . PointToScreen ( lastLocation ) ) ;
1811
+ ShowElementMenu ( this , eventArgs ) ;
1812
+ }
1813
+ return ;
1814
+ }
1815
+ }
1816
+
1679
1817
var element = FindElementAt ( transformed_location ) ;
1680
1818
if ( element == null )
1681
1819
{
@@ -1705,7 +1843,7 @@ protected override void OnClick(EventArgs e)
1705
1843
}
1706
1844
finally
1707
1845
{
1708
- base . OnClick ( e ) ;
1846
+ base . OnMouseClick ( e ) ;
1709
1847
}
1710
1848
}
1711
1849
#endregion
0 commit comments