Index: Core/Gui/src/Core.Gui/Core.Gui.csproj
===================================================================
diff -u -r434415295de74c310ce6d3cdd0100c28838cf9ea -r01cc95a0e9b04cbd3560c8f24be0641a31321b48
--- Core/Gui/src/Core.Gui/Core.Gui.csproj (.../Core.Gui.csproj) (revision 434415295de74c310ce6d3cdd0100c28838cf9ea)
+++ Core/Gui/src/Core.Gui/Core.Gui.csproj (.../Core.Gui.csproj) (revision 01cc95a0e9b04cbd3560c8f24be0641a31321b48)
@@ -120,6 +120,9 @@
UserControl
+
+ UserControl
+
@@ -132,6 +135,8 @@
+
+
Index: Core/Gui/src/Core.Gui/Forms/Map/MapLegendView.Designer.cs
===================================================================
diff -u
--- Core/Gui/src/Core.Gui/Forms/Map/MapLegendView.Designer.cs (revision 0)
+++ Core/Gui/src/Core.Gui/Forms/Map/MapLegendView.Designer.cs (revision 01cc95a0e9b04cbd3560c8f24be0641a31321b48)
@@ -0,0 +1,78 @@
+// Copyright (C) Stichting Deltares 2021. All rights reserved.
+//
+// This file is part of Riskeer.
+//
+// Riskeer is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+// All names, logos, and references to "Deltares" are registered trademarks of
+// Stichting Deltares and remain full property of Stichting Deltares at all times.
+// All rights reserved.
+
+namespace Core.Gui.Forms.Map
+{
+ partial class MapLegendView
+ {
+ ///
+ /// Required designer variable.
+ ///
+ 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
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.treeViewControl = new Core.Common.Controls.TreeView.TreeViewControl();
+ this.SuspendLayout();
+ //
+ // treeViewControl
+ //
+ this.treeViewControl.Data = null;
+ this.treeViewControl.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.treeViewControl.Location = new System.Drawing.Point(0, 0);
+ this.treeViewControl.Name = "treeViewControl";
+ this.treeViewControl.Size = new System.Drawing.Size(150, 150);
+ this.treeViewControl.TabIndex = 0;
+ //
+ // MapLegendView
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.treeViewControl);
+ this.Name = "MapLegendView";
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private Common.Controls.TreeView.TreeViewControl treeViewControl;
+ }
+}
Index: Core/Gui/src/Core.Gui/Forms/Map/MapLegendView.cs
===================================================================
diff -u
--- Core/Gui/src/Core.Gui/Forms/Map/MapLegendView.cs (revision 0)
+++ Core/Gui/src/Core.Gui/Forms/Map/MapLegendView.cs (revision 01cc95a0e9b04cbd3560c8f24be0641a31321b48)
@@ -0,0 +1,436 @@
+// Copyright (C) Stichting Deltares 2021. All rights reserved.
+//
+// This file is part of Riskeer.
+//
+// Riskeer is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program. If not, see .
+//
+// All names, logos, and references to "Deltares" are registered trademarks of
+// Stichting Deltares and remain full property of Stichting Deltares at all times.
+// All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using Core.Common.Controls.TreeView;
+using Core.Common.Controls.Views;
+using Core.Components.Gis.Data;
+using Core.Components.Gis.Data.Removable;
+using Core.Components.Gis.Forms;
+using Core.Components.Gis.Helpers;
+using Core.Gui.ContextMenu;
+using Core.Gui.Helpers;
+using Core.Gui.PresentationObjects.Map;
+using GuiResources = Core.Gui.Properties.Resources;
+
+namespace Core.Gui.Forms.Map
+{
+ ///
+ /// The view which shows the data that is added to a .
+ ///
+ public sealed partial class MapLegendView : UserControl, ISelectionProvider, IView
+ {
+ private readonly IContextMenuBuilderProvider contextMenuBuilderProvider;
+
+ private IMapControl mapControl;
+
+ public event EventHandler SelectionChanged;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The to create context menus.
+ /// Thrown when is null.
+ public MapLegendView(IContextMenuBuilderProvider contextMenuBuilderProvider)
+ {
+ if (contextMenuBuilderProvider == null)
+ {
+ throw new ArgumentNullException(nameof(contextMenuBuilderProvider),
+ $@"Cannot create a {typeof(MapLegendView).Name} when the context menu builder provider is null.");
+ }
+
+ this.contextMenuBuilderProvider = contextMenuBuilderProvider;
+ InitializeComponent();
+ Text = MapResources.General_Map;
+
+ RegisterTreeNodeInfos();
+
+ treeViewControl.SelectedDataChanged += TreeViewControlSelectedDataChanged;
+ }
+
+ ///
+ /// Gets or sets the for which this legend view is configured
+ /// to show the internal map data for.
+ ///
+ public IMapControl MapControl
+ {
+ private get
+ {
+ return mapControl;
+ }
+ set
+ {
+ mapControl = value;
+ Data = value?.Data;
+ }
+ }
+
+ public object Selection
+ {
+ get
+ {
+ return treeViewControl.SelectedData;
+ }
+ }
+
+ public object Data
+ {
+ get
+ {
+ return (MapDataCollectionContext) treeViewControl.Data;
+ }
+ set
+ {
+ treeViewControl.Data = value != null
+ ? new MapDataCollectionContext((MapDataCollection) value, null)
+ : null;
+ }
+ }
+
+ private void TreeViewControlSelectedDataChanged(object sender, EventArgs e)
+ {
+ SelectionChanged?.Invoke(this, new EventArgs());
+ }
+
+ private void RegisterTreeNodeInfos()
+ {
+ treeViewControl.RegisterTreeNodeInfo(new TreeNodeInfo
+ {
+ Text = context => context.WrappedData.Name,
+ Image = GetImage,
+ CanDrag = (context, parent) => true,
+ CanCheck = context => true,
+ CheckedState = context => context.WrappedData.IsVisible ? TreeNodeCheckedState.Checked : TreeNodeCheckedState.Unchecked,
+ OnNodeChecked = FeatureBasedMapDataContextOnNodeChecked,
+ CanRemove = (context, parent) => CanRemoveMapData((FeatureBasedMapData) context.WrappedData, parent),
+ OnNodeRemoved = (context, parent) => RemoveFromParent((FeatureBasedMapData) context.WrappedData, parent),
+ ContextMenuStrip = FeatureBasedMapDataContextContextMenuStrip
+ });
+
+ treeViewControl.RegisterTreeNodeInfo(new TreeNodeInfo
+ {
+ Text = context => context.WrappedData.Name,
+ Image = context => GuiResources.folder,
+ ChildNodeObjects = GetCollectionChildNodeObjects,
+ CanDrag = (context, parentData) => context.ParentMapData != null,
+ CanCheck = context => true,
+ CheckedState = MapDataCollectionContextCheckedState,
+ OnNodeChecked = MapDataCollectionContextOnNodeChecked,
+ CanDrop = MapDataCollectionCanDropAndInsert,
+ CanInsert = MapDataCollectionCanDropAndInsert,
+ OnDrop = MapDataCollectionOnDrop,
+ ContextMenuStrip = MapDataCollectionContextMenuStrip
+ });
+ }
+
+ private StrictContextMenuItem CreateZoomToExtentsItem(MapDataContext context)
+ {
+ StrictContextMenuItem zoomToExtentsItem = null;
+
+ if (context is MapDataCollectionContext)
+ {
+ zoomToExtentsItem = CreateZoomToExtentsItem((MapDataCollection) context.WrappedData);
+ }
+
+ if (context is FeatureBasedMapDataContext)
+ {
+ zoomToExtentsItem = CreateZoomToExtentsItem((FeatureBasedMapData) context.WrappedData);
+ }
+
+ return zoomToExtentsItem;
+ }
+
+ #region MapData
+
+ private StrictContextMenuItem CreateZoomToExtentsItem(FeatureBasedMapData nodeData)
+ {
+ bool hasFeatures = nodeData.Features.Any();
+ bool enabled = nodeData.IsVisible && hasFeatures;
+ string toolTip;
+
+ if (nodeData.IsVisible)
+ {
+ toolTip = hasFeatures
+ ? MapResources.MapLegendView_CreateZoomToExtentsItem_ZoomToAll_Tooltip
+ : MapResources.MapLegendView_CreateZoomToExtentsItem_NoFeatures_ZoomToAllDisabled_Tooltip;
+ }
+ else
+ {
+ toolTip = MapResources.MapLegendView_CreateZoomToExtentsItem_ZoomToAllDisabled_Tooltip;
+ }
+
+ return CreateZoomToExtentsItem(nodeData, toolTip, enabled);
+ }
+
+ private StrictContextMenuItem CreateZoomToExtentsItem(MapDataCollection nodeData)
+ {
+ FeatureBasedMapData[] featureBasedMapDatas = nodeData.GetFeatureBasedMapDataRecursively().ToArray();
+ var isVisible = false;
+ var hasFeatures = false;
+ foreach (FeatureBasedMapData mapData in featureBasedMapDatas)
+ {
+ if (mapData.IsVisible)
+ {
+ isVisible = true;
+
+ if (mapData.Features.Any())
+ {
+ hasFeatures = true;
+ break;
+ }
+ }
+ }
+
+ bool enabled = isVisible && hasFeatures;
+
+ string toolTip;
+
+ if (isVisible)
+ {
+ toolTip = hasFeatures
+ ? MapResources.MapLegendView_CreateZoomToExtentsItem_MapDataCollection_ZoomToAll_Tooltip
+ : MapResources.MapLegendView_CreateZoomToExtentsItem_MapDataCollection_NoFeatures_ZoomToAllDisabled_Tooltip;
+ }
+ else
+ {
+ toolTip = MapResources.MapLegendView_CreateZoomToExtentsItem_MapDataCollection_ZoomToAllDisabled_Tooltip;
+ }
+
+ 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
+ };
+ }
+
+ private static void NotifyMapDataParents(MapDataContext context)
+ {
+ foreach (MapDataCollection mapDataCollection in MapDataContextHelper.GetParentsFromContext(context))
+ {
+ mapDataCollection.NotifyObservers();
+ }
+ }
+
+ #endregion
+
+ #region FeatureBasedMapDataContext
+
+ private static Image GetImage(FeatureBasedMapDataContext 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 void FeatureBasedMapDataContextOnNodeChecked(FeatureBasedMapDataContext mapDataContext, object parentData)
+ {
+ mapDataContext.WrappedData.IsVisible = !mapDataContext.WrappedData.IsVisible;
+ mapDataContext.WrappedData.NotifyObservers();
+
+ NotifyMapDataParents(mapDataContext);
+ }
+
+ private static bool CanRemoveMapData(FeatureBasedMapData mapData, object parent)
+ {
+ return mapData is IRemovable && parent is MapDataCollectionContext;
+ }
+
+ private static void RemoveFromParent(FeatureBasedMapData dataToRemove, object parentData)
+ {
+ if (CanRemoveMapData(dataToRemove, parentData))
+ {
+ var mapDataCollectionContext = (MapDataCollectionContext) parentData;
+ var collection = (MapDataCollection) mapDataCollectionContext.WrappedData;
+ collection.Remove(dataToRemove);
+ collection.NotifyObservers();
+ }
+ }
+
+ private ContextMenuStrip FeatureBasedMapDataContextContextMenuStrip(FeatureBasedMapDataContext mapDataContext, object parentData, TreeViewControl treeView)
+ {
+ return contextMenuBuilderProvider.Get(mapDataContext, treeView)
+ .AddCustomItem(CreateZoomToExtentsItem(mapDataContext))
+ .AddSeparator()
+ .AddDeleteItem()
+ .AddSeparator()
+ .AddPropertiesItem()
+ .Build();
+ }
+
+ #endregion
+
+ #region MapDataCollectionContext
+
+ private static object[] GetCollectionChildNodeObjects(MapDataCollectionContext context)
+ {
+ var childObjects = new List