// Copyright (C) Stichting Deltares 2017. 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.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using Core.Common.Gui; using Core.Common.Gui.ContextMenu; using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.DikeProfiles; using Ringtoets.Common.Data.FailureMechanism; using Ringtoets.Common.Forms.ChangeHandlers; using Ringtoets.Common.Forms.Helpers; using Ringtoets.Common.Forms.PresentationObjects; using Ringtoets.Common.Forms.Properties; using RingtoetsCommonDataResources = Ringtoets.Common.Data.Properties.Resources; using BaseResources = Core.Common.Base.Properties.Resources; namespace Ringtoets.Common.Forms.TreeNodeInfos { /// /// This class represents a factory for creating . /// public static class RingtoetsContextMenuItemFactory { /// /// Creates a which is bound to the action of adding new calculation groups. /// /// The calculation group to add the new calculation groups to. /// The created . public static StrictContextMenuItem CreateAddCalculationGroupItem(CalculationGroup calculationGroup) { return new StrictContextMenuItem( Resources.CalculationGroup_Add_CalculationGroup, Resources.CalculationGroup_Add_CalculationGroup_Tooltip, Resources.AddFolderIcon, (o, args) => CreateCalculationGroup(calculationGroup)); } /// /// Creates a which is bound to the action of adding new calculations. /// /// The type of the calculation group context. /// The calculation group context belonging to the calculation group. /// The action for adding a calculation to the calculation group. /// The created . public static StrictContextMenuItem CreateAddCalculationItem( TCalculationContext calculationGroupContext, Action addCalculationAction) where TCalculationContext : ICalculationContext { return new StrictContextMenuItem( Resources.CalculationGroup_Add_Calculation, Resources.CalculationGroup_Add_Calculation_Tooltip, Resources.FailureMechanismIcon, (o, args) => addCalculationAction(calculationGroupContext)); } /// /// Creates a which is bound to the action of clearing the output of all calculations in the calculation group. /// /// The calculation group to clear the output for. /// The created . public static StrictContextMenuItem CreateClearAllCalculationOutputInGroupItem(CalculationGroup calculationGroup) { var clearAllItem = new StrictContextMenuItem( Resources.Clear_all_output, Resources.CalculationGroup_ClearOutput_ToolTip, Resources.ClearIcon, (o, args) => ClearAllCalculationOutputInGroup(calculationGroup)); if (!calculationGroup.HasOutput()) { clearAllItem.Enabled = false; clearAllItem.ToolTipText = Resources.CalculationGroup_ClearOutput_No_calculation_with_output_to_clear; } return clearAllItem; } /// /// Creates a which is bound to the action of performing all calculations in a calculation group. /// /// The type of the calculation group context. /// The calculation group to perform all calculations for. /// The calculation group context belonging to the calculation group. /// The action that performs all calculations. /// The function which determines whether the item should be enabled. If the /// item should not be enabled, then the reason for that should be returned by the function and will be shown as a tooltip. /// If the item should be enabled then the function should return a null or empty string. /// The created . public static StrictContextMenuItem CreatePerformAllCalculationsInGroupItem( CalculationGroup calculationGroup, TCalculationGroupContext calculationGroupContext, Action calculateAllAction, Func enableMenuItemFunction) where TCalculationGroupContext : ICalculationContext { var menuItem = new StrictContextMenuItem( Resources.Calculate_all, Resources.CalculationGroup_CalculateAll_ToolTip, Resources.CalculateAllIcon, (o, args) => calculateAllAction(calculationGroup, calculationGroupContext)); if (!calculationGroupContext.WrappedData.GetCalculations().Any()) { menuItem.Enabled = false; menuItem.ToolTipText = Resources.CalculationGroup_CalculateAll_No_calculations_to_run; } else { SetStateWithEnableFunction(calculationGroupContext, enableMenuItemFunction, menuItem); } return menuItem; } /// /// Creates a which is bound to the action of validating the input of each calculation /// in a calculation group. /// /// The type of the calculation group context. /// The calculation group context belonging to the calculation group. /// The action that validates all calculations. /// The function which determines whether the item should be enabled. If the /// item should not be enabled, then the reason for that should be returned by the function and will be shown as a tooltip. /// If the item should be enabled then the function should return a null or empty string. /// The created . public static StrictContextMenuItem CreateValidateAllCalculationsInGroupItem( TCalculationGroupContext calculationGroupContext, Action validateAllAction, Func enableMenuItemFunction) where TCalculationGroupContext : ICalculationContext { CalculationGroup calculationGroup = calculationGroupContext.WrappedData; var menuItem = new StrictContextMenuItem( Resources.Validate_all, Resources.CalculationGroup_Validate_all_ToolTip, Resources.ValidateAllIcon, (o, args) => validateAllAction(calculationGroupContext)); if (!calculationGroup.GetCalculations().Any()) { menuItem.Enabled = false; menuItem.ToolTipText = Resources.ValidateAll_No_calculations_to_validate; } else { SetStateWithEnableFunction(calculationGroupContext, enableMenuItemFunction, menuItem); } return menuItem; } /// /// Creates a which is bound to the action of performing a calculation. /// /// The type of the calculation. /// The type of the calculation context. /// The calculation to perform. /// The calculation context belonging to the calculation. /// The action that performs the calculation. /// The function which determines whether the item should be enabled. If the /// item should not be enabled, then the reason for that should be returned by the function and will be shown as a tooltip. /// If the item should be enabled then the function should return a null or empty string. /// The created . public static StrictContextMenuItem CreatePerformCalculationItem( TCalculation calculation, TCalculationContext calculationContext, Action calculateAction, Func enableMenuItemFunction) where TCalculationContext : ICalculationContext where TCalculation : ICalculation { var menuItem = new StrictContextMenuItem( Resources.Calculate, Resources.Calculate_ToolTip, Resources.CalculateIcon, (o, args) => calculateAction(calculation, calculationContext)); SetStateWithEnableFunction(calculationContext, enableMenuItemFunction, menuItem); return menuItem; } /// /// Creates a which is bound to the action of validating the input of a calculation. /// /// The type of the calculation context. /// The context containing the calculation to validate. /// The action that performs the validation. /// The function which determines whether the item should be enabled. If the /// item should not be enabled, then the reason for that should be returned by the function and will be shown as a tooltip. /// If the item should be enabled then the function should return a null or empty string. /// The created . public static StrictContextMenuItem CreateValidateCalculationItem( TCalculationContext calculation, Action validateAction, Func enableMenuItemFunction) where TCalculationContext : ICalculationContext { var menuItem = new StrictContextMenuItem( Resources.Validate, Resources.Validate_ToolTip, Resources.ValidateIcon, (o, args) => validateAction(calculation)); SetStateWithEnableFunction(calculation, enableMenuItemFunction, menuItem); return menuItem; } /// /// Creates a which is bound to the action of clearing the output of a calculation. /// /// The calculation to clear the output for. /// The created . public static StrictContextMenuItem CreateClearCalculationOutputItem(ICalculation calculation) { var clearOutputItem = new StrictContextMenuItem( Resources.Clear_output, Resources.Clear_output_ToolTip, Resources.ClearIcon, (o, args) => ClearCalculationOutput(calculation)); if (!calculation.HasOutput) { clearOutputItem.Enabled = false; clearOutputItem.ToolTipText = Resources.ClearOutput_No_output_to_clear; } return clearOutputItem; } /// /// Creates a which is bound to the action of clearing the output of all calculations in a failure mechanism. /// /// The failure mechanism to clear the output for. /// The created . public static StrictContextMenuItem CreateClearAllCalculationOutputInFailureMechanismItem(IFailureMechanism failureMechanism) { var clearAllItem = new StrictContextMenuItem( Resources.Clear_all_output, Resources.Clear_all_output_ToolTip, Resources.ClearIcon, (o, args) => ClearAllCalculationOutputInFailureMechanism(failureMechanism)); if (!failureMechanism.Calculations.Any(c => c.HasOutput)) { clearAllItem.Enabled = false; clearAllItem.ToolTipText = Resources.CalculationGroup_ClearOutput_No_calculation_with_output_to_clear; } return clearAllItem; } /// /// Creates a which is bound to the action of performing all calculations in a failure mechanism. /// /// The type of the failure mechanism context. /// The failure mechanism context belonging to the failure mechanism. /// The action that performs all calculations. /// The function which determines whether the item should be enabled. If the /// item should not be enabled, then the reason for that should be returned by the function and will be shown as a tooltip. /// If the item should be enabled then the function should return a null or empty string. /// The created . /// When returns a string, the item will be disabled and the string will be shown in the tooltip. public static StrictContextMenuItem CreatePerformAllCalculationsInFailureMechanismItem( TFailureMechanismContext failureMechanismContext, Action calculateAllAction, Func enableMenuItemFunction) where TFailureMechanismContext : IFailureMechanismContext { var menuItem = new StrictContextMenuItem( Resources.Calculate_all, Resources.Calculate_all_ToolTip, Resources.CalculateAllIcon, (o, args) => calculateAllAction(failureMechanismContext)); if (!failureMechanismContext.WrappedData.Calculations.Any()) { menuItem.Enabled = false; menuItem.ToolTipText = Resources.FailureMechanism_CreateCalculateAllItem_No_calculations_to_run; } else { SetStateWithEnableFunction(failureMechanismContext, enableMenuItemFunction, menuItem); } return menuItem; } /// /// Creates a which is bound to the action of performing all calculations in a failure mechanism. /// /// The type of the failure mechanism. /// The failure mechanism to validate the calculations of. /// The action that validates all calculations. /// The function which determines whether the item should be enabled. If the /// item should not be enabled, then the reason for that should be returned by the function and will be shown as a tooltip. /// If the item should be enabled then the function should return a null or empty string. /// The created . public static StrictContextMenuItem CreateValidateAllCalculationsInFailureMechanismItem( TFailureMechanismContext failureMechanism, Action validateAllAction, Func enableMenuItemFunction) where TFailureMechanismContext : IFailureMechanismContext { var menuItem = new StrictContextMenuItem( Resources.Validate_all, Resources.FailureMechanism_Validate_all_ToolTip, Resources.ValidateAllIcon, (o, args) => validateAllAction(failureMechanism)); if (!failureMechanism.WrappedData.Calculations.Any()) { menuItem.Enabled = false; menuItem.ToolTipText = Resources.ValidateAll_No_calculations_to_validate; } else { SetStateWithEnableFunction(failureMechanism, enableMenuItemFunction, menuItem); } return menuItem; } /// /// Creates a which is bound to the action of changing the relevance of a failure mechanism. /// /// The type of the failure mechanism context. /// The failure mechanism context belonging to the failure mechanism. /// The action to perform when relevance changes. /// The created . public static StrictContextMenuItem CreateToggleRelevancyOfFailureMechanismItem( TFailureMechanismContext failureMechanismContext, Action onChangeAction) where TFailureMechanismContext : IFailureMechanismContext { bool isRelevant = failureMechanismContext.WrappedData.IsRelevant; Bitmap checkboxImage = isRelevant ? Resources.Checkbox_ticked : Resources.Checkbox_empty; return new StrictContextMenuItem( Resources.FailureMechanismContextMenuStrip_Is_relevant, Resources.FailureMechanism_IsRelevant_Description, checkboxImage, (sender, args) => { onChangeAction?.Invoke(failureMechanismContext); failureMechanismContext.WrappedData.IsRelevant = !isRelevant; failureMechanismContext.WrappedData.NotifyObservers(); }); } /// /// Creates a which is bound to the action when updating /// the of a . /// /// The type of calculation input that has can have a foreshore profile. /// The calculation to update. /// Object responsible for inquiring the required data. /// The action to perform when the foreshore profile is updated. /// The created . public static StrictContextMenuItem CreateUpdateForshoreProfileOfCalculationItem( ICalculation calculation, IInquiryHelper inquiryHelper, Action> updateAction) where TCalculationInput : ICalculationInput, IHasForeshoreProfile { TCalculationInput input = calculation.InputParameters; bool hasForeshoreProfile = input.ForeshoreProfile != null && !input.IsForeshoreProfileParametersSynchronized; string toolTipMessage = hasForeshoreProfile ? Resources.CreateUpdateForshoreProfileOfCalculationItem_Update_calculation_with_ForeshoreProfile_ToolTip : Resources.CreateUpdateForshoreProfileOfCalculationItem_Update_calculation_no_ForeshoreProfile_ToolTip; var menuItem = new StrictContextMenuItem( Resources.CreateUpdateForshoreProfileOfCalculationItem_Update_ForeshoreProfile_data, toolTipMessage, Resources.UpdateItemIcon, (o, args) => { UpdateForeshoreProfileDependentDataOfCalculation(calculation, inquiryHelper, updateAction); }) { Enabled = hasForeshoreProfile }; return menuItem; } private static void UpdateForeshoreProfileDependentDataOfCalculation( ICalculation calculation, IInquiryHelper inquiryHelper, Action> updateAction) where TCalculationInput : ICalculationInput, IHasForeshoreProfile { string message = Resources.UpdateForshoreProfileOfCalculation_Confirm_calculation_output_cleared_when_updating_ForeshoreProfile_dependent_data; if (ForeshoreProfileDependentDataShouldUpdate(new[] { calculation }, message, inquiryHelper )) { updateAction(calculation); } } private static bool ForeshoreProfileDependentDataShouldUpdate(IEnumerable calculations, string query, IInquiryHelper inquiryHelper) { var changeHandler = new CalculationChangeHandler(calculations, query, inquiryHelper); return !changeHandler.RequireConfirmation() || changeHandler.InquireConfirmation(); } private static void SetStateWithEnableFunction(T context, Func enableFunction, StrictContextMenuItem menuItem) { string validationText = enableFunction?.Invoke(context); if (!string.IsNullOrEmpty(validationText)) { menuItem.Enabled = false; menuItem.ToolTipText = validationText; } } private static void ClearAllCalculationOutputInFailureMechanism(IFailureMechanism failureMechanism) { if (MessageBox.Show(Resources.FailureMechanism_ContextMenuStrip_Are_you_sure_clear_all_output, BaseResources.Confirm, MessageBoxButtons.OKCancel) != DialogResult.OK) { return; } foreach (ICalculation calc in failureMechanism.Calculations.Where(c => c.HasOutput)) { calc.ClearOutput(); calc.NotifyObservers(); } } private static void CreateCalculationGroup(CalculationGroup calculationGroup) { calculationGroup.Children.Add(new CalculationGroup { Name = NamingHelper.GetUniqueName(calculationGroup.Children, RingtoetsCommonDataResources.CalculationGroup_DefaultName, c => c.Name) }); calculationGroup.NotifyObservers(); } private static void ClearAllCalculationOutputInGroup(CalculationGroup calculationGroup) { if (MessageBox.Show(Resources.CalculationGroup_ClearOutput_Are_you_sure_clear_all_output, BaseResources.Confirm, MessageBoxButtons.OKCancel) != DialogResult.OK) { return; } calculationGroup.ClearCalculationOutput(); } private static void ClearCalculationOutput(ICalculation calculation) { if (MessageBox.Show(Resources.Calculation_ContextMenuStrip_Are_you_sure_clear_output, BaseResources.Confirm, MessageBoxButtons.OKCancel) != DialogResult.OK) { return; } calculation.ClearOutput(); calculation.NotifyObservers(); } } }