Index: Ringtoets/Common/src/Ringtoets.Common.Forms/Ringtoets.Common.Forms.csproj =================================================================== diff -u -rb1a215180352084c8f320439c1893c639917f338 -r87445dcecde875ada5513431df8ca2d01a57f742 --- Ringtoets/Common/src/Ringtoets.Common.Forms/Ringtoets.Common.Forms.csproj (.../Ringtoets.Common.Forms.csproj) (revision b1a215180352084c8f320439c1893c639917f338) +++ Ringtoets/Common/src/Ringtoets.Common.Forms/Ringtoets.Common.Forms.csproj (.../Ringtoets.Common.Forms.csproj) (revision 87445dcecde875ada5513431df8ca2d01a57f742) @@ -61,7 +61,7 @@ Resources.resx - + UserControl Index: Ringtoets/Common/src/Ringtoets.Common.Forms/TreeNodeInfos/CalculationTreeNodeInfoFactory.cs =================================================================== diff -u --- Ringtoets/Common/src/Ringtoets.Common.Forms/TreeNodeInfos/CalculationTreeNodeInfoFactory.cs (revision 0) +++ Ringtoets/Common/src/Ringtoets.Common.Forms/TreeNodeInfos/CalculationTreeNodeInfoFactory.cs (revision 87445dcecde875ada5513431df8ca2d01a57f742) @@ -0,0 +1,303 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU 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.Linq; +using System.Windows.Forms; +using Core.Common.Controls.TreeView; +using Core.Common.Gui; +using Core.Common.Gui.ContextMenu; +using Ringtoets.Common.Data.Calculation; +using Ringtoets.Common.Data.FailureMechanism; +using Ringtoets.Common.Forms.Helpers; +using Ringtoets.Common.Forms.PresentationObjects; +using Ringtoets.Common.Forms.Properties; + +using RingtoetsCommonDataResources = Ringtoets.Common.Data.Properties.Resources; + +namespace Ringtoets.Common.Forms.TreeNodeInfos +{ + /// + /// Factory for creating objects. + /// + public static class CalculationTreeNodeInfoFactory + { + /// + /// Creates a object for a calculation group context of the type . + /// + /// The type of calculation group context to create a object for. + /// The function for obtaining child node objects. + /// The action for adding a calculation to the calculation group. + /// The gui to use. + /// A object. + public static TreeNodeInfo CreateCalculationGroupContextTreeNodeInfo( + Func childNodeObjects, + Action addCalculation, + IGui gui) + where TCalculationGroupContext : ICalculationContext + { + return new TreeNodeInfo + { + Text = context => context.WrappedData.Name, + Image = context => Resources.GeneralFolderIcon, + EnsureVisibleOnCreate = context => true, + ChildNodeObjects = childNodeObjects, + ContextMenuStrip = (context, parentData, treeViewControl) => ContextMenuStrip(context, parentData, treeViewControl, addCalculation, gui), + CanRename = (context, parentData) => IsNestedGroup(parentData), + OnNodeRenamed = (context, newName) => + { + context.WrappedData.Name = newName; + context.NotifyObservers(); + }, + CanRemove = (context, parentData) => IsNestedGroup(parentData), + OnNodeRemoved = (context, parentData) => + { + var parentGroup = (ICalculationContext) parentData; + + parentGroup.WrappedData.Children.Remove(context.WrappedData); + parentGroup.NotifyObservers(); + }, + CanDrag = (context, parentData) => IsNestedGroup(parentData), + CanInsert = CanDropOrInsert, + CanDrop = CanDropOrInsert, + OnDrop = OnDrop + }; + } + + /// + /// This method adds a context menu item for creating new calculation groups. + /// + /// The builder to add the context menu item too. + /// The calculation group involved. + public static void AddCreateCalculationGroupItem(IContextMenuBuilder builder, CalculationGroup calculationGroup) + { + var createCalculationGroupItem = new StrictContextMenuItem( + Resources.CalculationGroup_Add_CalculationGroup, + Resources.Add_calculation_group_to_calculation_group_tooltip, + Resources.AddFolderIcon, + (o, args) => + { + var calculation = new CalculationGroup + { + Name = NamingHelper.GetUniqueName(calculationGroup.Children, RingtoetsCommonDataResources.CalculationGroup_DefaultName, c => c.Name) + }; + calculationGroup.Children.Add(calculation); + calculationGroup.NotifyObservers(); + }); + + builder.AddCustomItem(createCalculationGroupItem); + } + + /// + /// This method adds a context menu item for creating new calculations. + /// + /// The builder to add the context menu item too. + /// The calculation group context involved. + /// The action for adding a calculation to the calculation group. + public static void AddCreateCalculationItem(IContextMenuBuilder builder, TCalculationGroupContext calculationGroupContext, Action addCalculation) where TCalculationGroupContext : ICalculationContext + { + var createCalculationItem = new StrictContextMenuItem( + Resources.CalculationGroup_Add_Calculation, + Resources.Add_calculation_to_calculation_group_tooltip, + Resources.FailureMechanismIcon, + (o, args) => { addCalculation(calculationGroupContext); }); + + builder.AddCustomItem(createCalculationItem); + } + + private static bool IsNestedGroup(object parentData) + { + return parentData is ICalculationContext; + } + + private static ContextMenuStrip ContextMenuStrip(TCalculationGroupContext nodeData, object parentData, TreeViewControl treeViewControl, Action addCalculation, IGui gui) where TCalculationGroupContext : ICalculationContext + { + var group = nodeData.WrappedData; + var builder = gui.Get(nodeData, treeViewControl); + var isNestedGroup = IsNestedGroup(parentData); + + if (!isNestedGroup) + { + builder + .AddOpenItem() + .AddSeparator(); + } + + AddCreateCalculationGroupItem(builder, group); + AddCreateCalculationItem(builder, nodeData, addCalculation); + builder.AddSeparator(); + + if (isNestedGroup) + { + builder.AddRenameItem(); + builder.AddDeleteItem(); + builder.AddSeparator(); + } + + return builder + .AddImportItem() + .AddExportItem() + .AddSeparator() + .AddExpandAllItem() + .AddCollapseAllItem() + .AddSeparator() + .AddPropertiesItem() + .Build(); + } + + private static bool CanDropOrInsert(object draggedData, object targetData) + { + var calculationContext = draggedData as ICalculationContext; + return calculationContext != null && ReferenceEquals(calculationContext.FailureMechanism, ((ICalculationContext)targetData).FailureMechanism); + } + + private static void OnDrop(object droppedData, object newParentData, object oldParentData, int position, TreeViewControl treeViewControl) + { + ICalculationBase calculationItem = ((ICalculationContext) droppedData).WrappedData; + var originalOwnerContext = oldParentData as ICalculationContext; + var targetContext = newParentData as ICalculationContext; + + if (calculationItem != null && originalOwnerContext != null && targetContext != null) + { + var sourceCalculationGroup = originalOwnerContext.WrappedData; + var targetCalculationGroup = targetContext.WrappedData; + + var isMoveWithinSameContainer = ReferenceEquals(sourceCalculationGroup, targetCalculationGroup); + + DroppingCalculationInContainerStrategy dropHandler = GetDragDropStrategy(isMoveWithinSameContainer, sourceCalculationGroup, targetCalculationGroup); + dropHandler.Execute(droppedData, calculationItem, position, treeViewControl); + } + } + + private static DroppingCalculationInContainerStrategy GetDragDropStrategy(bool isMoveWithinSameContainer, CalculationGroup sourceCalculationGroup, CalculationGroup targetCalculationGroup) + { + return isMoveWithinSameContainer + ? (DroppingCalculationInContainerStrategy)new DroppingCalculationWithinSameContainer(sourceCalculationGroup, targetCalculationGroup) + : new DroppingCalculationToNewContainer(sourceCalculationGroup, targetCalculationGroup); + } + + #region Nested Types: DroppingPipingCalculationInContainerStrategy and implementations + + /// + /// Strategy pattern implementation for dealing with drag & dropping a + /// onto data. + /// + private abstract class DroppingCalculationInContainerStrategy + { + private readonly CalculationGroup sourceCalculationGroup; + protected readonly CalculationGroup targetCalculationGroup; + + protected DroppingCalculationInContainerStrategy(CalculationGroup sourceCalculationGroup, CalculationGroup targetCalculationGroup) + { + this.sourceCalculationGroup = sourceCalculationGroup; + this.targetCalculationGroup = targetCalculationGroup; + } + + /// + /// Perform the drag & drop operation. + /// + /// The dragged data. + /// The calculation item wrapped by . + /// The index of the new position within the new owner's collection. + /// The tree view control which is at stake. + public virtual void Execute(object draggedData, ICalculationBase calculationBase, int newPosition, TreeViewControl treeViewControl) + { + MoveCalculationItemToNewOwner(calculationBase, newPosition); + + NotifyObservers(); + } + + /// + /// Moves the instance to its new location. + /// + /// The instance to be relocated. + /// The index in the new + /// owner within its . + protected void MoveCalculationItemToNewOwner(ICalculationBase calculationBase, int position) + { + sourceCalculationGroup.Children.Remove(calculationBase); + targetCalculationGroup.Children.Insert(position, calculationBase); + } + + /// + /// Notifies observers of the change in state. + /// + protected virtual void NotifyObservers() + { + sourceCalculationGroup.NotifyObservers(); + } + } + + /// + /// Strategy implementation for rearranging the order of an + /// within a through a drag & drop action. + /// + private class DroppingCalculationWithinSameContainer : DroppingCalculationInContainerStrategy + { + /// + /// Initializes a new instance of the class. + /// + /// The calculation group that is the target of the drag & drop operation. + /// The calculation group that is the original owner of the dragged item. + public DroppingCalculationWithinSameContainer(CalculationGroup sourceCalculationGroup, CalculationGroup targetCalculationGroup) : + base(sourceCalculationGroup, targetCalculationGroup) { } + } + + /// + /// Strategy implementation for moving an from + /// one to another using a drag & drop action. + /// + private class DroppingCalculationToNewContainer : DroppingCalculationInContainerStrategy + { + /// + /// Initializes a new instance of the class. + /// + /// The calculation group that is the original owner of the dragged item. + /// The calculation group that is the target of the drag & drop operation. + public DroppingCalculationToNewContainer(CalculationGroup sourceCalculationGroup, CalculationGroup targetCalculationGroup) : + base(sourceCalculationGroup, targetCalculationGroup) { } + + public override void Execute(object draggedData, ICalculationBase calculationBase, int newPosition, TreeViewControl treeViewControl) + { + MoveCalculationItemToNewOwner(calculationBase, newPosition); + + NotifyObservers(); + + // Try to start a name edit action when an item with the same name was already present + if (targetCalculationGroup.Children.Except(new[] + { + calculationBase + }).Any(c => c.Name.Equals(calculationBase.Name))) + { + treeViewControl.TryRenameNodeForData(draggedData); + } + } + + protected override void NotifyObservers() + { + base.NotifyObservers(); + targetCalculationGroup.NotifyObservers(); + } + } + + #endregion + } +} \ No newline at end of file Fisheye: Tag 87445dcecde875ada5513431df8ca2d01a57f742 refers to a dead (removed) revision in file `Ringtoets/Common/src/Ringtoets.Common.Forms/TreeNodeInfos/TreeNodeInfoFactory.cs'. Fisheye: No comparison available. Pass `N' to diff? Index: Ringtoets/GrassCoverErosionInwards/src/Ringtoets.GrassCoverErosionInwards.Plugin/GrassCoverErosionInwardsGuiPlugin.cs =================================================================== diff -u -rb1a215180352084c8f320439c1893c639917f338 -r87445dcecde875ada5513431df8ca2d01a57f742 --- Ringtoets/GrassCoverErosionInwards/src/Ringtoets.GrassCoverErosionInwards.Plugin/GrassCoverErosionInwardsGuiPlugin.cs (.../GrassCoverErosionInwardsGuiPlugin.cs) (revision b1a215180352084c8f320439c1893c639917f338) +++ Ringtoets/GrassCoverErosionInwards/src/Ringtoets.GrassCoverErosionInwards.Plugin/GrassCoverErosionInwardsGuiPlugin.cs (.../GrassCoverErosionInwardsGuiPlugin.cs) (revision 87445dcecde875ada5513431df8ca2d01a57f742) @@ -70,7 +70,7 @@ FailureMechanismContextMenuStrip, Gui); - yield return TreeNodeInfoFactory.CreateCalculationGroupContextTreeNodeInfo(CalculationGroupContextChildNodeObjects, context => AddCalculation(context.FailureMechanism, context.WrappedData), Gui); + yield return CalculationTreeNodeInfoFactory.CreateCalculationGroupContextTreeNodeInfo(CalculationGroupContextChildNodeObjects, context => AddCalculation(context.FailureMechanism, context.WrappedData), Gui); yield return new TreeNodeInfo { Index: Ringtoets/Piping/src/Ringtoets.Piping.Plugin/PipingGuiPlugin.cs =================================================================== diff -u -r6821ff075261a98f42221ccc796d007ca11a93fe -r87445dcecde875ada5513431df8ca2d01a57f742 --- Ringtoets/Piping/src/Ringtoets.Piping.Plugin/PipingGuiPlugin.cs (.../PipingGuiPlugin.cs) (revision 6821ff075261a98f42221ccc796d007ca11a93fe) +++ Ringtoets/Piping/src/Ringtoets.Piping.Plugin/PipingGuiPlugin.cs (.../PipingGuiPlugin.cs) (revision 87445dcecde875ada5513431df8ca2d01a57f742) @@ -235,7 +235,7 @@ private TreeNodeInfo CreatePipingCalculationGroupContextTreeNodeInfo() { - var treeNodeInfo = TreeNodeInfoFactory.CreateCalculationGroupContextTreeNodeInfo(PipingCalculationGroupContextChildNodeObjects, null, Gui); + var treeNodeInfo = CalculationTreeNodeInfoFactory.CreateCalculationGroupContextTreeNodeInfo(PipingCalculationGroupContextChildNodeObjects, null, Gui); treeNodeInfo.ContextMenuStrip = PipingCalculationGroupContextContextMenuStrip; treeNodeInfo.OnNodeRemoved = PipingCalculationGroupContextOnNodeRemoved;