Index: Riskeer/Piping/src/Riskeer.Piping.Forms/PropertyClasses/PipingFailureMechanismSectionConfigurationsProperties.cs
===================================================================
diff -u
--- Riskeer/Piping/src/Riskeer.Piping.Forms/PropertyClasses/PipingFailureMechanismSectionConfigurationsProperties.cs (revision 0)
+++ Riskeer/Piping/src/Riskeer.Piping.Forms/PropertyClasses/PipingFailureMechanismSectionConfigurationsProperties.cs (revision 660e8b24bbfd2f862779a8d4d6ab36f698cf2757)
@@ -0,0 +1,125 @@
+// Copyright (C) Stichting Deltares and State of the Netherlands 2023. 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 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.ComponentModel;
+using Core.Common.Base;
+using Core.Common.Util.Attributes;
+using Core.Gui.Attributes;
+using Core.Gui.Converters;
+using Core.Gui.PropertyBag;
+using Riskeer.Common.Data.FailureMechanism;
+using Riskeer.Common.Forms.Helpers;
+using Riskeer.Common.Forms.PropertyClasses;
+using Riskeer.Piping.Data;
+using RiskeerCommonFormsResources = Riskeer.Common.Forms.Properties.Resources;
+
+namespace Riskeer.Piping.Forms.PropertyClasses
+{
+ ///
+ /// ViewModel of for the properties panel
+ /// to show a collection of .
+ ///
+ public class PipingFailureMechanismSectionConfigurationsProperties : ObjectProperties, IDisposable
+ {
+ private readonly Func getPropertyChangeHandlerFunc;
+ private readonly Observer failureMechanismObserver;
+ private readonly RecursiveObserver, FailureMechanismSectionConfiguration> sectionConfigurationsObserver;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The failure mechanism to show the section configurations for.
+ ///
+ /// Thrown when any parameter is null.
+ public PipingFailureMechanismSectionConfigurationsProperties(PipingFailureMechanism failureMechanism,
+ Func getPropertyChangeHandlerFunc)
+ {
+ if (failureMechanism == null)
+ {
+ throw new ArgumentNullException(nameof(failureMechanism));
+ }
+
+ if (getPropertyChangeHandlerFunc == null)
+ {
+ throw new ArgumentNullException(nameof(getPropertyChangeHandlerFunc));
+ }
+
+ this.getPropertyChangeHandlerFunc = getPropertyChangeHandlerFunc;
+
+ data = failureMechanism;
+
+ failureMechanismObserver = new Observer(OnRefreshRequired)
+ {
+ Observable = data
+ };
+
+ sectionConfigurationsObserver = new RecursiveObserver, FailureMechanismSectionConfiguration>(
+ OnRefreshRequired,
+ sectionConfiguration => sectionConfiguration)
+ {
+ Observable = data.SectionConfigurations
+ };
+ }
+
+ [PropertyOrder(1)]
+ [ResourcesCategory(typeof(RiskeerCommonFormsResources), nameof(RiskeerCommonFormsResources.Categories_General))]
+ [ResourcesDisplayName(typeof(RiskeerCommonFormsResources), nameof(RiskeerCommonFormsResources.ObservableCollectionWithSourcePath_SourcePath_DisplayName))]
+ [ResourcesDescription(typeof(RiskeerCommonFormsResources), nameof(RiskeerCommonFormsResources.FailureMechanismSections_SourcePath_Description))]
+ public string SourcePath
+ {
+ get
+ {
+ return data.FailureMechanismSectionSourcePath;
+ }
+ }
+
+ [PropertyOrder(2)]
+ [ResourcesCategory(typeof(RiskeerCommonFormsResources), nameof(RiskeerCommonFormsResources.Categories_General))]
+ [ResourcesDisplayName(typeof(RiskeerCommonFormsResources), nameof(RiskeerCommonFormsResources.FailureMechanismSections_DisplayName))]
+ [ResourcesDescription(typeof(RiskeerCommonFormsResources), nameof(RiskeerCommonFormsResources.FailureMechanismSections_Description))]
+ [TypeConverter(typeof(ExpandableArrayConverter))]
+ public PipingFailureMechanismSectionConfigurationProperties[] SectionConfigurations
+ {
+ get
+ {
+ return FailureMechanismSectionPresentationHelper.CreatePresentableFailureMechanismSectionConfigurations(
+ data.SectionConfigurations,
+ CreateFailureMechanismSectionConfigurationProperties);
+ }
+ }
+
+ public void Dispose()
+ {
+ failureMechanismObserver.Dispose();
+ sectionConfigurationsObserver.Dispose();
+ }
+
+ private PipingFailureMechanismSectionConfigurationProperties CreateFailureMechanismSectionConfigurationProperties(
+ PipingFailureMechanismSectionConfiguration sectionConfiguration,
+ double sectionStart,
+ double sectionEnd)
+ {
+ return new PipingFailureMechanismSectionConfigurationProperties(sectionConfiguration, sectionStart, sectionEnd,
+ data.GeneralInput.B, getPropertyChangeHandlerFunc(sectionConfiguration));
+ }
+ }
+}
\ No newline at end of file
Index: Riskeer/Piping/test/Riskeer.Piping.Forms.Test/PipingFailureMechanismSectionConfigurationsPropertiesTest.cs
===================================================================
diff -u
--- Riskeer/Piping/test/Riskeer.Piping.Forms.Test/PipingFailureMechanismSectionConfigurationsPropertiesTest.cs (revision 0)
+++ Riskeer/Piping/test/Riskeer.Piping.Forms.Test/PipingFailureMechanismSectionConfigurationsPropertiesTest.cs (revision 660e8b24bbfd2f862779a8d4d6ab36f698cf2757)
@@ -0,0 +1,212 @@
+// Copyright (C) Stichting Deltares and State of the Netherlands 2023. 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 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.ComponentModel;
+using System.Linq;
+using Core.Common.Base;
+using Core.Common.TestUtil;
+using Core.Gui.Converters;
+using Core.Gui.PropertyBag;
+using Core.Gui.TestUtil;
+using NUnit.Framework;
+using Rhino.Mocks;
+using Riskeer.Common.Data.FailureMechanism;
+using Riskeer.Common.Data.TestUtil;
+using Riskeer.Common.Forms.PropertyClasses;
+using Riskeer.Piping.Data;
+using Riskeer.Piping.Forms.PropertyClasses;
+
+namespace Riskeer.Piping.Forms.Test
+{
+ [TestFixture]
+ public class PipingFailureMechanismSectionConfigurationsPropertiesTest
+ {
+ [Test]
+ public void Constructor_FailureMechanismNull_ThrowsArgumentNullException()
+ {
+ // Setup
+ var mocks = new MockRepository();
+ var changeHandler = mocks.Stub();
+ mocks.ReplayAll();
+
+ // Call
+ void Call() => new PipingFailureMechanismSectionConfigurationsProperties(null, configuration => changeHandler);
+
+ // Assert
+ var exception = Assert.Throws(Call);
+ Assert.AreEqual("failureMechanism", exception.ParamName);
+ mocks.VerifyAll();
+ }
+
+ [Test]
+ public void Constructor_GetPropertyChangeHandlerFuncNull_ThrowsArgumentNullException()
+ {
+ // Setup
+ var failureMechanism = new PipingFailureMechanism();
+
+ // Call
+ void Call() => new PipingFailureMechanismSectionConfigurationsProperties(failureMechanism, null);
+
+ // Assert
+ var exception = Assert.Throws(Call);
+ Assert.AreEqual("getPropertyChangeHandlerFunc", exception.ParamName);
+ }
+
+ [Test]
+ public void Constructor_ExpectedValues()
+ {
+ // Setup
+ const string sourcePath = "just//a//section//path";
+
+ var mocks = new MockRepository();
+ var changeHandler = mocks.Stub();
+ mocks.ReplayAll();
+
+ FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection();
+ var failureMechanism = new PipingFailureMechanism();
+ failureMechanism.SetSections(new[]
+ {
+ section
+ }, sourcePath);
+
+ // Call
+ using (var properties = new PipingFailureMechanismSectionConfigurationsProperties(failureMechanism, configuration => changeHandler))
+ {
+ // Assert
+ Assert.IsInstanceOf>(properties);
+ Assert.IsInstanceOf(properties);
+ Assert.AreSame(failureMechanism, properties.Data);
+
+ TestHelper.AssertTypeConverter(
+ nameof(FailureMechanismSectionsProperties.Sections));
+ IObservableEnumerable sectionConfigurations = failureMechanism.SectionConfigurations;
+ Assert.AreEqual(sectionConfigurations.Count(), properties.SectionConfigurations.Length);
+
+ double sectionStart = 0;
+ for (var i = 0; i < sectionConfigurations.Count(); i++)
+ {
+ PipingFailureMechanismSectionConfiguration sectionConfiguration = sectionConfigurations.ElementAt(i);
+ PipingFailureMechanismSectionConfigurationProperties property = properties.SectionConfigurations[i];
+ Assert.AreSame(sectionConfiguration.Section, property.Data);
+
+ double sectionEnd = sectionStart + sectionConfiguration.Section.Length;
+ Assert.AreEqual(sectionStart, property.SectionStart, property.SectionStart.GetAccuracy());
+ Assert.AreEqual(sectionEnd, property.SectionEnd, property.SectionEnd.GetAccuracy());
+ sectionStart = sectionEnd;
+ }
+
+ Assert.AreEqual(sourcePath, properties.SourcePath);
+ }
+ }
+
+ [Test]
+ public void Constructor_Always_PropertiesHaveExpectedAttributesValues()
+ {
+ // Setup
+ var mocks = new MockRepository();
+ var changeHandler = mocks.Stub();
+ mocks.ReplayAll();
+
+ var failureMechanism = new PipingFailureMechanism();
+
+ // Call
+ using (var properties = new PipingFailureMechanismSectionConfigurationsProperties(failureMechanism, configuration => changeHandler))
+ {
+ // Assert
+ PropertyDescriptorCollection dynamicProperties = PropertiesTestHelper.GetAllVisiblePropertyDescriptors(properties);
+ Assert.AreEqual(2, dynamicProperties.Count);
+ const string generalCategoryName = "Algemeen";
+
+ PropertyDescriptor sourcePathProperty = dynamicProperties[0];
+ PropertiesTestHelper.AssertRequiredPropertyDescriptorProperties(sourcePathProperty,
+ generalCategoryName,
+ "Bronlocatie",
+ "De locatie van het bestand waaruit de vakindeling is geïmporteerd.",
+ true);
+
+ PropertyDescriptor sectionsProperty = dynamicProperties[1];
+ PropertiesTestHelper.AssertRequiredPropertyDescriptorProperties(sectionsProperty,
+ generalCategoryName,
+ "Vakindeling",
+ "Vakindeling waarmee de waterkering voor dit faalmechanisme is " +
+ "geschematiseerd ten behoeve van de beoordeling.",
+ true);
+ mocks.VerifyAll();
+ }
+ }
+
+ [Test]
+ public void GivenPropertyControlWithData_WhenFailureMechanismUpdated_RefreshRequiredEventRaised()
+ {
+ // Given
+ var mocks = new MockRepository();
+ var changeHandler = mocks.Stub();
+ mocks.ReplayAll();
+
+ var failureMechanism = new PipingFailureMechanism();
+
+ // Call
+ using (var properties = new PipingFailureMechanismSectionConfigurationsProperties(failureMechanism, configuration => changeHandler))
+ {
+ var refreshRequiredRaised = 0;
+ properties.RefreshRequired += (sender, args) => refreshRequiredRaised++;
+
+ // When
+ failureMechanism.NotifyObservers();
+
+ // Then
+ Assert.AreEqual(1, refreshRequiredRaised);
+ }
+ }
+
+ [Test]
+ public void GivenPropertyControlWithData_WhenFailureMechanismSectionConfigurationUpdated_RefreshRequiredEventRaised()
+ {
+ // Given
+ var mocks = new MockRepository();
+ var changeHandler = mocks.Stub();
+ mocks.ReplayAll();
+
+ FailureMechanismSection section = FailureMechanismSectionTestFactory.CreateFailureMechanismSection();
+ var failureMechanism = new PipingFailureMechanism();
+ FailureMechanismTestHelper.SetSections(failureMechanism, new[]
+ {
+ section
+ });
+
+ var sectionConfiguration = failureMechanism.SectionConfigurations.First();
+
+ // Call
+ using (var properties = new PipingFailureMechanismSectionConfigurationsProperties(failureMechanism, configuration => changeHandler))
+ {
+ var refreshRequiredRaised = 0;
+ properties.RefreshRequired += (sender, args) => refreshRequiredRaised++;
+
+ // When
+ sectionConfiguration.NotifyObservers();
+
+ // Then
+ Assert.AreEqual(1, refreshRequiredRaised);
+ }
+ }
+ }
+}
\ No newline at end of file