Index: Core/Plugins/src/Core.Plugins.Map/Legend/MapLegendView.cs =================================================================== diff -u -r2a81f01756e227d5ce93717b21b87e8a5cd5fcbb -r3098804e6dc9d7aae2733700bfb5772eab1956d7 --- Core/Plugins/src/Core.Plugins.Map/Legend/MapLegendView.cs (.../MapLegendView.cs) (revision 2a81f01756e227d5ce93717b21b87e8a5cd5fcbb) +++ Core/Plugins/src/Core.Plugins.Map/Legend/MapLegendView.cs (.../MapLegendView.cs) (revision 3098804e6dc9d7aae2733700bfb5772eab1956d7) @@ -1,4 +1,4 @@ -// Copyright (C) Stichting Deltares 2018. All rights reserved. +// Copyright (C) Stichting Deltares 2018. All rights reserved. // // This file is part of Ringtoets. // @@ -20,14 +20,17 @@ // All rights reserved. using System; +using System.Drawing; using System.Linq; using System.Windows.Forms; +using Core.Common.Base; using Core.Common.Controls.TreeView; using Core.Common.Controls.Views; using Core.Common.Gui.ContextMenu; using Core.Components.Gis.Data; using Core.Components.Gis.Data.Removable; using Core.Components.Gis.Forms; +using Core.Plugins.Map.PresentationObjects; using MapResources = Core.Plugins.Map.Properties.Resources; using GuiResources = Core.Common.Gui.Properties.Resources; @@ -87,6 +90,12 @@ { get { + var mapDataContext = treeViewControl.SelectedData as MapDataContext; + if (mapDataContext != null) + { + return mapDataContext.WrappedData; + } + return treeViewControl.SelectedData; } } @@ -110,53 +119,37 @@ private void RegisterTreeNodeInfos() { - treeViewControl.RegisterTreeNodeInfo(new TreeNodeInfo + treeViewControl.RegisterTreeNodeInfo(new TreeNodeInfo { - Text = mapPointData => mapPointData.Name, - Image = mapPointData => MapResources.PointsIcon, - ContextMenuStrip = (nodeData, parentData, treeView) => CreateFeatureBasedMapDataContextMenu(nodeData, treeView), - CanRemove = CanRemoveMapData, - OnNodeRemoved = RemoveFromParent, - CanDrag = (mapPointData, parentData) => true, - CanCheck = mapPointData => true, - IsChecked = mapPointData => mapPointData.IsVisible, - OnNodeChecked = MapDataOnNodeChecked + Text = context => context.WrappedData.Name, + Image = GetImage, + ChildNodeObjects = MapDataContextGetChildNodeObjects, + CanDrag = (context, o) => true, + CanCheck = context => !(context.WrappedData is MapDataCollection), + IsChecked = context => context.WrappedData.IsVisible, + OnNodeChecked = MapDataContextOnNodeChecked, + CanDrop = MapDataContextCanDropAndInsert, + CanInsert = MapDataContextCanDropAndInsert, + OnDrop = MapDataContextOnDrop, + CanRemove = (context, parent) => CanRemoveMapData(context.WrappedData, parent), + OnNodeRemoved = (context, parent) => RemoveFromParent(context.WrappedData, parent), + ContextMenuStrip = (nodeData, parentData, treeView) => contextMenuBuilderProvider.Get(nodeData.WrappedData, treeView) + .AddCustomItem(CreateZoomToExtentsItem(nodeData.WrappedData)) + .AddSeparator() + .AddDeleteItem() + .AddSeparator() + .AddPropertiesItem() + .Build() }); - treeViewControl.RegisterTreeNodeInfo(new TreeNodeInfo - { - Text = mapLineData => mapLineData.Name, - Image = mapLineData => MapResources.LineIcon, - ContextMenuStrip = (nodeData, parentData, treeView) => CreateFeatureBasedMapDataContextMenu(nodeData, treeView), - CanRemove = CanRemoveMapData, - OnNodeRemoved = RemoveFromParent, - CanDrag = (mapLineData, parentData) => true, - CanCheck = mapLineData => true, - IsChecked = mapLineData => mapLineData.IsVisible, - OnNodeChecked = MapDataOnNodeChecked - }); - - treeViewControl.RegisterTreeNodeInfo(new TreeNodeInfo - { - Text = mapPolygonData => mapPolygonData.Name, - Image = mapPolygonData => MapResources.AreaIcon, - ContextMenuStrip = (nodeData, parentData, treeView) => CreateFeatureBasedMapDataContextMenu(nodeData, treeView), - CanRemove = CanRemoveMapData, - OnNodeRemoved = RemoveFromParent, - CanDrag = (mapPolygonData, parentData) => true, - CanCheck = mapPolygonData => true, - IsChecked = mapPolygonData => mapPolygonData.IsVisible, - OnNodeChecked = MapDataOnNodeChecked - }); - treeViewControl.RegisterTreeNodeInfo(new TreeNodeInfo { Text = mapDataCollection => mapDataCollection.Name, Image = mapDataCollection => GuiResources.folder, - ChildNodeObjects = mapDataCollection => mapDataCollection.Collection.Reverse().Cast().ToArray(), - CanDrop = MapControlCanDrop, - CanInsert = MapControlCanInsert, - OnDrop = MapControlOnDrop, + ChildNodeObjects = GetCollectionChildNodeObjects, + CanDrop = MapDataCollectionCanDropAndInsert, + CanInsert = MapDataCollectionCanDropAndInsert, + OnDrop = MapDataCollectionOnDrop, ContextMenuStrip = (mapDataCollection, parentData, treeView) => contextMenuBuilderProvider.Get(mapDataCollection, treeView) .AddCustomImportItem( MapResources.MapLegendView_MapDataCollectionContextMenuStrip_Add_MapLayer, @@ -170,49 +163,40 @@ }); } - private ContextMenuStrip CreateFeatureBasedMapDataContextMenu(FeatureBasedMapData nodeData, TreeViewControl treeView) + private static object[] GetChildNodeObjects(MapDataCollection mapDataCollection) { - return contextMenuBuilderProvider.Get(nodeData, treeView) - .AddCustomItem(CreateZoomToExtentsItem(nodeData)) - .AddSeparator() - .AddDeleteItem() - .AddSeparator() - .AddPropertiesItem() - .Build(); + return mapDataCollection.Collection.Reverse() + .Select(mapData => new MapDataContext(mapData, mapDataCollection)) + .Cast().ToArray(); } - private static bool CanRemoveMapData(MapData mapData, object parent) + private void NotifyObserversOfData(MapData mapData) { - return mapData is IRemovable && parent is MapDataCollection; + mapData.NotifyObservers(); + + var observableParent = Data as IObservable; + observableParent?.NotifyObservers(); } - private static void RemoveFromParent(MapData dataToRemove, object parentData) + #region MapData + + private StrictContextMenuItem CreateZoomToExtentsItem(MapData nodeData) { - if (CanRemoveMapData(dataToRemove, parentData)) + StrictContextMenuItem zoomToExtentsItem = null; + + var collectionNodeData = nodeData as MapDataCollection; + if (collectionNodeData != null) { - var collection = (MapDataCollection) parentData; - collection.Remove(dataToRemove); - collection.NotifyObservers(); + zoomToExtentsItem = CreateZoomToExtentsItem(collectionNodeData); } - } - private StrictContextMenuItem CreateZoomToExtentsItem(MapData nodeData, string toolTip, bool isEnabled) - { - return new StrictContextMenuItem($"&{MapResources.Ribbon_ZoomToAll}", - toolTip, - MapResources.ZoomToAllIcon, - (sender, args) => MapControl?.ZoomToAllVisibleLayers(nodeData)) + var featureBasedNodeData = nodeData as FeatureBasedMapData; + if (featureBasedNodeData != null) { - Enabled = isEnabled - }; - } + zoomToExtentsItem = CreateZoomToExtentsItem(featureBasedNodeData); + } - #region MapData - - private static void MapDataOnNodeChecked(FeatureBasedMapData featureBasedMapData, object parentData) - { - featureBasedMapData.IsVisible = !featureBasedMapData.IsVisible; - featureBasedMapData.NotifyObservers(); + return zoomToExtentsItem; } private StrictContextMenuItem CreateZoomToExtentsItem(FeatureBasedMapData nodeData) @@ -235,30 +219,6 @@ return CreateZoomToExtentsItem(nodeData, toolTip, enabled); } - #endregion - - #region MapDataCollection - - private static bool MapControlCanDrop(object draggedData, object targetData) - { - return draggedData is MapData; - } - - private static bool MapControlCanInsert(object draggedData, object targetData) - { - return draggedData is MapData; - } - - private static void MapControlOnDrop(object droppedData, object newParentData, object oldParentData, int position, TreeViewControl control) - { - var mapData = (MapData) droppedData; - var target = (MapDataCollection) newParentData; - - target.Remove(mapData); - target.Insert(target.Collection.Count() - position, mapData); // Note: target is the same as the previous parent in this case - target.NotifyObservers(); - } - private StrictContextMenuItem CreateZoomToExtentsItem(MapDataCollection nodeData) { FeatureBasedMapData[] featureBasedMapDatas = nodeData.GetFeatureBasedMapDataRecursively().ToArray(); @@ -296,6 +256,119 @@ return CreateZoomToExtentsItem(nodeData, toolTip, enabled); } + private StrictContextMenuItem CreateZoomToExtentsItem(MapData nodeData, string toolTip, bool isEnabled) + { + return new StrictContextMenuItem($"&{MapResources.Ribbon_ZoomToAll}", + toolTip, + MapResources.ZoomToAllIcon, + (sender, args) => MapControl?.ZoomToAllVisibleLayers(nodeData)) + { + Enabled = isEnabled + }; + } + #endregion + + #region MapDataContext + + private static Image GetImage(MapDataContext context) + { + if (context.WrappedData is MapPointData) + { + return MapResources.PointsIcon; + } + + if (context.WrappedData is MapLineData) + { + return MapResources.LineIcon; + } + + if (context.WrappedData is MapPolygonData) + { + return MapResources.AreaIcon; + } + + return GuiResources.folder; + } + + private static object[] MapDataContextGetChildNodeObjects(MapDataContext mapDataContext) + { + var collection = mapDataContext.WrappedData as MapDataCollection; + return collection != null ? GetChildNodeObjects(collection) : new object[0]; + } + + private void MapDataContextOnNodeChecked(MapDataContext mapDataContext, object parentData) + { + mapDataContext.WrappedData.IsVisible = !mapDataContext.WrappedData.IsVisible; + NotifyObserversOfData(mapDataContext.WrappedData); + } + + private static bool MapDataContextCanDropAndInsert(object draggedData, object targetData) + { + var draggedDataContext = (MapDataContext) draggedData; + var targetDataContext = (MapDataContext) targetData; + + return draggedDataContext.ParentMapData.Equals(targetDataContext.WrappedData); + } + + private static void MapDataContextOnDrop(object droppedData, object newParentData, object oldParentData, int position, TreeViewControl control) + { + var mapContext = (MapDataContext) droppedData; + var sourceContext = oldParentData as MapDataContext; + + MapData mapData = mapContext.WrappedData; + var parent = (MapDataCollection) (sourceContext != null ? sourceContext.WrappedData : oldParentData); + + parent.Remove(mapData); + parent.Insert(parent.Collection.Count() - position, mapData); + parent.NotifyObservers(); + } + + private static bool CanRemoveMapData(MapData mapData, object parent) + { + return mapData is IRemovable && parent is MapDataCollection; + } + + private static void RemoveFromParent(MapData dataToRemove, object parentData) + { + if (CanRemoveMapData(dataToRemove, parentData)) + { + var collection = (MapDataCollection) parentData; + collection.Remove(dataToRemove); + collection.NotifyObservers(); + } + } + + #endregion + + #region MapDataCollection + + private static object[] GetCollectionChildNodeObjects(MapDataCollection mapDataCollection) + { + return GetChildNodeObjects(mapDataCollection); + } + + private static bool MapDataCollectionCanDropAndInsert(object draggedData, object targetData) + { + var draggedDataContext = (MapDataContext) draggedData; + var targetDataContext = targetData as MapDataContext; + object targetDataObject = targetDataContext != null ? targetDataContext.ParentMapData : targetData; + + return draggedDataContext.ParentMapData.Equals(targetDataObject); + } + + private static void MapDataCollectionOnDrop(object droppedData, object newParentData, object oldParentData, int position, TreeViewControl control) + { + var mapDataContext = (MapDataContext) droppedData; + + MapData mapData = mapDataContext.WrappedData; + var parent = (MapDataCollection) oldParentData; + + parent.Remove(mapData); + parent.Insert(parent.Collection.Count() - position, mapData); // Note: target is the same as the previous parent in this case + parent.NotifyObservers(); + } + + #endregion } } \ No newline at end of file Index: Core/Plugins/test/Core.Plugins.Chart.Test/Legend/ChartLegendViewTest.cs =================================================================== diff -u -r2a81f01756e227d5ce93717b21b87e8a5cd5fcbb -r3098804e6dc9d7aae2733700bfb5772eab1956d7 --- Core/Plugins/test/Core.Plugins.Chart.Test/Legend/ChartLegendViewTest.cs (.../ChartLegendViewTest.cs) (revision 2a81f01756e227d5ce93717b21b87e8a5cd5fcbb) +++ Core/Plugins/test/Core.Plugins.Chart.Test/Legend/ChartLegendViewTest.cs (.../ChartLegendViewTest.cs) (revision 3098804e6dc9d7aae2733700bfb5772eab1956d7) @@ -75,7 +75,7 @@ } [Test] - public void Data_ChartControl_DataSet() + public void Data_ChartDataCollection_DataSet() { // Setup var mocks = new MockRepository(); Index: Core/Plugins/test/Core.Plugins.Map.Test/Legend/MapLegendViewTest.cs =================================================================== diff -u -r2a81f01756e227d5ce93717b21b87e8a5cd5fcbb -r3098804e6dc9d7aae2733700bfb5772eab1956d7 --- Core/Plugins/test/Core.Plugins.Map.Test/Legend/MapLegendViewTest.cs (.../MapLegendViewTest.cs) (revision 2a81f01756e227d5ce93717b21b87e8a5cd5fcbb) +++ Core/Plugins/test/Core.Plugins.Map.Test/Legend/MapLegendViewTest.cs (.../MapLegendViewTest.cs) (revision 3098804e6dc9d7aae2733700bfb5772eab1956d7) @@ -20,20 +20,17 @@ // All rights reserved. using System; -using System.Linq; using System.Threading; using System.Windows.Forms; -using Core.Common.Base.Geometry; using Core.Common.Controls.TreeView; using Core.Common.Controls.Views; using Core.Common.Gui.ContextMenu; using Core.Common.TestUtil; using Core.Common.Util.Reflection; using Core.Components.Gis.Data; -using Core.Components.Gis.Features; using Core.Components.Gis.Forms; -using Core.Components.Gis.Geometries; using Core.Plugins.Map.Legend; +using Core.Plugins.Map.PresentationObjects; using Core.Plugins.Map.Properties; using NUnit.Framework; using Rhino.Mocks; @@ -108,66 +105,6 @@ } [Test] - public void Data_MapPointData_DataSet() - { - // Setup - using (var view = new MapLegendView(contextMenuBuilderProvider)) - { - var mapData = new MapPointData("test data") - { - Features = CreateFeatures() - }; - - // Call - view.Data = mapData; - - // Assert - Assert.AreSame(mapData, view.Data); - Assert.IsInstanceOf(view.Data); - } - } - - [Test] - public void Data_MapLineData_DataSet() - { - // Setup - using (var view = new MapLegendView(contextMenuBuilderProvider)) - { - var mapData = new MapLineData("test data") - { - Features = CreateFeatures() - }; - - // Call - view.Data = mapData; - - // Assert - Assert.AreSame(mapData, view.Data); - Assert.IsInstanceOf(view.Data); - } - } - - [Test] - public void Data_MapPolygonData_DataSet() - { - // Setup - using (var view = new MapLegendView(contextMenuBuilderProvider)) - { - var mapData = new MapPolygonData("test data") - { - Features = CreateFeatures() - }; - - // Call - view.Data = mapData; - - // Assert - Assert.AreSame(mapData, view.Data); - Assert.IsInstanceOf(view.Data); - } - } - - [Test] public void Data_Null_NullSet() { // Setup @@ -241,7 +178,7 @@ [Test] [Apartment(ApartmentState.STA)] - public void Selection_Always_ReturnsSelectedNodeData() + public void Selection_NestedNodeData_ReturnsWrappedObjectData() { // Setup var mapData = new MapLineData("line data"); @@ -254,10 +191,11 @@ Data = mapDataCollection }) { - var treeViewControl = TypeUtils.GetField(view, "treeViewControl"); + var context = new MapDataContext(mapData, mapDataCollection); + var treeViewControl = TypeUtils.GetField(view, "treeViewControl"); WindowsFormsTestHelper.Show(treeViewControl); - treeViewControl.TrySelectNodeForData(mapData); + treeViewControl.TrySelectNodeForData(context); // Call object selection = view.Selection; @@ -271,6 +209,35 @@ [Test] [Apartment(ApartmentState.STA)] + public void Selection_RootNodeData_ReturnsObjectData() + { + // Setup + var mapData = new MapLineData("line data"); + var mapDataCollection = new MapDataCollection("collection"); + + mapDataCollection.Add(mapData); + + using (var view = new MapLegendView(contextMenuBuilderProvider) + { + Data = mapDataCollection + }) + { + var treeViewControl = TypeUtils.GetField(view, "treeViewControl"); + WindowsFormsTestHelper.Show(treeViewControl); + treeViewControl.TrySelectNodeForData(mapDataCollection); + + // Call + object selection = view.Selection; + + // Assert + Assert.AreSame(mapDataCollection, selection); + } + + WindowsFormsTestHelper.CloseAll(); + } + + [Test] + [Apartment(ApartmentState.STA)] public void GivenMapLegendView_WhenSelectedNodeChanged_SelectionChangedFired() { // Given @@ -291,7 +258,8 @@ view.SelectionChanged += (sender, args) => selectionChangedCount++; // When - treeViewControl.TrySelectNodeForData(mapData); + var context = new MapDataContext(mapData, mapDataCollection); + treeViewControl.TrySelectNodeForData(context); // Then Assert.AreEqual(1, selectionChangedCount); @@ -322,19 +290,5 @@ WindowsFormsTestHelper.CloseAll(); } - - private static MapFeature[] CreateFeatures() - { - return new[] - { - new MapFeature(new[] - { - new MapGeometry(new[] - { - Enumerable.Empty() - }) - }) - }; - } } } \ No newline at end of file