// 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();
}
}
}