Index: Core/Components/src/Core.Components.GraphSharp.Forms/PointedTreeGraphControl.Designer.cs =================================================================== diff -u -rb11a871d609824c8b414cecf94977c3923c3d09a -r672857a9fcd0dfdcaec314524d580af98894536f --- Core/Components/src/Core.Components.GraphSharp.Forms/PointedTreeGraphControl.Designer.cs (.../PointedTreeGraphControl.Designer.cs) (revision b11a871d609824c8b414cecf94977c3923c3d09a) +++ Core/Components/src/Core.Components.GraphSharp.Forms/PointedTreeGraphControl.Designer.cs (.../PointedTreeGraphControl.Designer.cs) (revision 672857a9fcd0dfdcaec314524d580af98894536f) @@ -28,19 +28,6 @@ /// private System.ComponentModel.IContainer components = null; - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - #region Component Designer generated code /// Index: Core/Components/src/Core.Components.GraphSharp.Forms/PointedTreeGraphControl.cs =================================================================== diff -u -rd0717faa6f35e514ae6f2dd1c1abd701de8cfab7 -r672857a9fcd0dfdcaec314524d580af98894536f --- Core/Components/src/Core.Components.GraphSharp.Forms/PointedTreeGraphControl.cs (.../PointedTreeGraphControl.cs) (revision d0717faa6f35e514ae6f2dd1c1abd701de8cfab7) +++ Core/Components/src/Core.Components.GraphSharp.Forms/PointedTreeGraphControl.cs (.../PointedTreeGraphControl.cs) (revision 672857a9fcd0dfdcaec314524d580af98894536f) @@ -20,6 +20,8 @@ // All rights reserved. using System; +using System.Collections.Generic; +using System.ComponentModel; using System.Windows; using System.Windows.Forms; using System.Windows.Input; @@ -38,11 +40,14 @@ /// public partial class PointedTreeGraphControl : UserControl, IPointedTreeGraphControl { + private readonly List drawnGraphNodeList = new List(); private ZoomControl zoomControl; private PointedTreeGraphLayout graphLayout; private GraphNode data; private PointedTreeGraph graph; + public event EventHandler SelectionChanged; + /// /// Creates a new instance of . /// @@ -60,7 +65,7 @@ } set { - graph.Clear(); + ClearData(); data = value; @@ -71,6 +76,18 @@ } } + public GraphNode Selection { get; private set; } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + ClearData(); + components?.Dispose(); + } + base.Dispose(disposing); + } + private void InitializeGraph() { zoomControl = new ZoomControl @@ -96,10 +113,31 @@ wpfElementHost.Child = zoomControl; } + private void ClearData() + { + foreach (DrawnGraphNode drawnGraphNode in drawnGraphNodeList) + { + drawnGraphNode.Vertex.PropertyChanged -= VertexOnPropertyChanged; + } + + graph.Clear(); + drawnGraphNodeList.Clear(); + } + private void DrawNode(GraphNode node, PointedTreeElementVertex parentVertex = null) { PointedTreeElementVertex vertex = GraphNodeConverter.Convert(node); + vertex.PropertyChanged += VertexOnPropertyChanged; + + var drawnGraphNode = new DrawnGraphNode + { + GraphNode = node, + Vertex = vertex + }; + + drawnGraphNodeList.Add(drawnGraphNode); + graph.AddVertex(vertex); node.ChildNodes.ForEachElementDo(cn => DrawNode(cn, vertex)); @@ -110,6 +148,37 @@ } } + private void VertexOnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(PointedTreeElementVertex.IsSelected)) + { + var changedVertex = sender as PointedTreeElementVertex; + if (changedVertex != null && changedVertex.IsSelected) + { + foreach (DrawnGraphNode drawnGraphNode in drawnGraphNodeList) + { + if (drawnGraphNode.Vertex.IsSelected && drawnGraphNode.Vertex != changedVertex) + { + drawnGraphNode.Vertex.IsSelected = false; + } + + if (drawnGraphNode.Vertex == changedVertex && changedVertex.IsSelected) + { + Selection = drawnGraphNode.GraphNode; + OnSelectionChanged(e); + } + } + } + } + } + + private void OnSelectionChanged(PropertyChangedEventArgs e) + { + SelectionChanged?.Invoke(this, e); + } + + #region Zooming + private void ZoomControl_MouseWheel(object sender, MouseWheelEventArgs e) { double deltaZoom = GetZoomDelta(e.Delta); @@ -136,5 +205,23 @@ return Math.Max(1.0 / zoomControl.MaxZoomDelta, Math.Min(zoomControl.MaxZoomDelta, delta / -zoomControl.ZoomDeltaMultiplier + 1.0)); } + + #endregion + + /// + /// Lookup class for administration related to drawn vertices. + /// + private class DrawnGraphNode + { + /// + /// The graph node which the drawn is based upon. + /// + public GraphNode GraphNode { get; set; } + + /// + /// The drawn vertex. + /// + public PointedTreeElementVertex Vertex { get; set; } + } } } \ No newline at end of file Index: Core/Components/src/Core.Components.PointedTree.Forms/IPointedTreeGraphControl.cs =================================================================== diff -u -rb11a871d609824c8b414cecf94977c3923c3d09a -r672857a9fcd0dfdcaec314524d580af98894536f --- Core/Components/src/Core.Components.PointedTree.Forms/IPointedTreeGraphControl.cs (.../IPointedTreeGraphControl.cs) (revision b11a871d609824c8b414cecf94977c3923c3d09a) +++ Core/Components/src/Core.Components.PointedTree.Forms/IPointedTreeGraphControl.cs (.../IPointedTreeGraphControl.cs) (revision 672857a9fcd0dfdcaec314524d580af98894536f) @@ -19,6 +19,7 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; using Core.Components.PointedTree.Data; namespace Core.Components.PointedTree.Forms @@ -29,8 +30,18 @@ public interface IPointedTreeGraphControl { /// + /// Fired when the selection has been changed. + /// + event EventHandler SelectionChanged; + + /// /// Gets or sets the root node of the control. /// GraphNode Data { get; set; } + + /// + /// Gets the selected ; or null if nothing is selected. + /// + GraphNode Selection { get; } } } \ No newline at end of file Index: Core/Components/test/Core.Components.GraphSharp.Forms.Test/PointedTreeGraphControlTest.cs =================================================================== diff -u -rd0717faa6f35e514ae6f2dd1c1abd701de8cfab7 -r672857a9fcd0dfdcaec314524d580af98894536f --- Core/Components/test/Core.Components.GraphSharp.Forms.Test/PointedTreeGraphControlTest.cs (.../PointedTreeGraphControlTest.cs) (revision d0717faa6f35e514ae6f2dd1c1abd701de8cfab7) +++ Core/Components/test/Core.Components.GraphSharp.Forms.Test/PointedTreeGraphControlTest.cs (.../PointedTreeGraphControlTest.cs) (revision 672857a9fcd0dfdcaec314524d580af98894536f) @@ -48,6 +48,7 @@ Assert.IsInstanceOf(graphControl); Assert.IsNull(graphControl.Data); + Assert.IsNull(graphControl.Selection); Assert.AreEqual(1, graphControl.Controls.Count); @@ -163,5 +164,71 @@ Assert.AreEqual(0, graph.EdgeCount); } } + + [Test] + public void GivenControlWithData_WhenVertexSelected_SelectionSetToGraphNodeAndSelectionChangedFired() + { + // Given + using (var graphControl = new PointedTreeGraphControl()) + { + var childNode = new GraphNode("node 2", new GraphNode[0], true); + var node = new GraphNode("node 1", new[] + { + childNode + }, true); + + graphControl.Data = node; + + var elementHost = graphControl.Controls[0] as ElementHost; + var zoomControl = (ZoomControl) elementHost.Child; + var graphLayout = (PointedTreeGraphLayout) zoomControl.Content; + PointedTreeGraph graph = graphLayout.Graph; + + var selectionChanged = 0; + graphControl.SelectionChanged += (sender, args) => selectionChanged++; + + // Precondition + Assert.IsNull(graphControl.Selection); + + // When + PointedTreeElementVertex selectedVertex = graph.Vertices.ElementAt(1); + selectedVertex.IsSelected = true; + + // Then + Assert.AreSame(childNode, graphControl.Selection); + Assert.AreEqual(1, selectionChanged); + } + } + + [Test] + public void GivenControlWithSelectedVertex_WhenOtherVertexSelected_FirstSelectedVertexUnselected() + { + // Given + using (var graphControl = new PointedTreeGraphControl()) + { + var node = new GraphNode("node 1", new[] + { + new GraphNode("node 2", new GraphNode[0], true) + }, true); + + graphControl.Data = node; + + var elementHost = graphControl.Controls[0] as ElementHost; + var zoomControl = (ZoomControl) elementHost.Child; + var graphLayout = (PointedTreeGraphLayout) zoomControl.Content; + PointedTreeGraph graph = graphLayout.Graph; + + PointedTreeElementVertex firstSelectedVertex = graph.Vertices.ElementAt(1); + firstSelectedVertex.IsSelected = true; + + PointedTreeElementVertex newSelectedVertex = graph.Vertices.First(); + + // When + newSelectedVertex.IsSelected = true; + + // Then + Assert.IsFalse(firstSelectedVertex.IsSelected); + } + } } } \ No newline at end of file