Index: Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Data/ClosingStructuresCalculation.cs =================================================================== diff -u -r98929f84fbf311bd19d8e61cc8499cdb40b22ea0 -r93baa4ee308eff5a157e37bd2b4fe148a45806af --- Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Data/ClosingStructuresCalculation.cs (.../ClosingStructuresCalculation.cs) (revision 98929f84fbf311bd19d8e61cc8499cdb40b22ea0) +++ Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Data/ClosingStructuresCalculation.cs (.../ClosingStructuresCalculation.cs) (revision 93baa4ee308eff5a157e37bd2b4fe148a45806af) @@ -77,5 +77,10 @@ { return Output; } + + public override string ToString() + { + return Name; + } } } \ No newline at end of file Index: Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Forms/Views/ClosingStructuresScenariosView.Designer.cs =================================================================== diff -u -r9fffdfe86ac1685eb9369e2190c26181e3613cb1 -r93baa4ee308eff5a157e37bd2b4fe148a45806af --- Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Forms/Views/ClosingStructuresScenariosView.Designer.cs (.../ClosingStructuresScenariosView.Designer.cs) (revision 9fffdfe86ac1685eb9369e2190c26181e3613cb1) +++ Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Forms/Views/ClosingStructuresScenariosView.Designer.cs (.../ClosingStructuresScenariosView.Designer.cs) (revision 93baa4ee308eff5a157e37bd2b4fe148a45806af) @@ -28,19 +28,6 @@ /// 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 /// Index: Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Forms/Views/ClosingStructuresScenariosView.cs =================================================================== diff -u -r2190156241cd307f0d9d784f2ff50ed339c3beac -r93baa4ee308eff5a157e37bd2b4fe148a45806af --- Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Forms/Views/ClosingStructuresScenariosView.cs (.../ClosingStructuresScenariosView.cs) (revision 2190156241cd307f0d9d784f2ff50ed339c3beac) +++ Ringtoets/ClosingStructures/src/Ringtoets.ClosingStructures.Forms/Views/ClosingStructuresScenariosView.cs (.../ClosingStructuresScenariosView.cs) (revision 93baa4ee308eff5a157e37bd2b4fe148a45806af) @@ -19,9 +19,15 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; +using System.Collections.Generic; +using System.Linq; using System.Windows.Forms; +using Core.Common.Base; using Core.Common.Controls.Views; using Ringtoets.ClosingStructures.Data; +using Ringtoets.ClosingStructures.Utils; +using Ringtoets.Common.Data.Calculation; namespace Ringtoets.ClosingStructures.Forms.Views { @@ -32,19 +38,104 @@ /// public partial class ClosingStructuresScenariosView : UserControl, IView { + private readonly RecursiveObserver calculationInputObserver; + private readonly RecursiveObserver calculationGroupObserver; + private readonly Observer failureMechanismObserver; + private ClosingStructuresFailureMechanism failureMechanism; + private CalculationGroup data; + /// /// Creates a new instance of . /// public ClosingStructuresScenariosView() { InitializeComponent(); + + failureMechanismObserver = new Observer(UpdateDataGridViewDataSource); + + // The concat is needed to observe the input of calculations in child groups. + calculationInputObserver = new RecursiveObserver( + UpdateDataGridViewDataSource, cg => cg.Children.Concat(cg.Children.OfType().Select(c => c.GetObservableInput()))); + calculationGroupObserver = new RecursiveObserver(UpdateDataGridViewDataSource, c => c.Children); } - public object Data { get; set; } - /// /// Gets or sets the failure mechanism. /// - public ClosingStructuresFailureMechanism FailureMechanism { get; set; } + public ClosingStructuresFailureMechanism FailureMechanism + { + get + { + return failureMechanism; + } + set + { + failureMechanism = value; + failureMechanismObserver.Observable = failureMechanism; + UpdateDataGridViewDataSource(); + } + } + + public object Data + { + get + { + return data; + } + set + { + data = value as CalculationGroup; + + calculationInputObserver.Observable = data; + calculationGroupObserver.Observable = data; + + UpdateDataGridViewDataSource(); + } + } + + protected override void OnLoad(EventArgs e) + { + UpdateDataGridViewDataSource(); + base.OnLoad(e); + } + + protected override void Dispose(bool disposing) + { + if (failureMechanismObserver != null) + { + failureMechanismObserver.Dispose(); + } + calculationInputObserver.Dispose(); + calculationGroupObserver.Dispose(); + + if (disposing && (components != null)) + { + components.Dispose(); + } + + base.Dispose(disposing); + } + + private void UpdateDataGridViewDataSource() + { + scenarioSelectionControl.EndEdit(); + + if (failureMechanism == null || failureMechanism.SectionResults == null || data == null || data.Children == null) + { + scenarioSelectionControl.ClearDataSource(); + } + else + { + var calculations = data.GetCalculations().ToArray(); + + Dictionary> calculationsPerSegment = + ClosingStructuresHelper.CollectCalculationsPerSection(failureMechanism.Sections, + calculations.OfType()); + + var scenarioRows = failureMechanism.SectionResults.Select(sr => new ClosingStructuresScenarioRow(sr)).ToList(); + + scenarioSelectionControl.UpdateDataGridViewDataSource(calculations, scenarioRows, calculationsPerSegment); + } + } } -} +} \ No newline at end of file Index: Ringtoets/ClosingStructures/test/Ringtoets.ClosingStructures.Data.Test/ClosingStructuresCalculationTest.cs =================================================================== diff -u -rc7da0846a135f849273407e16fe52237371e8f7a -r93baa4ee308eff5a157e37bd2b4fe148a45806af --- Ringtoets/ClosingStructures/test/Ringtoets.ClosingStructures.Data.Test/ClosingStructuresCalculationTest.cs (.../ClosingStructuresCalculationTest.cs) (revision c7da0846a135f849273407e16fe52237371e8f7a) +++ Ringtoets/ClosingStructures/test/Ringtoets.ClosingStructures.Data.Test/ClosingStructuresCalculationTest.cs (.../ClosingStructuresCalculationTest.cs) (revision 93baa4ee308eff5a157e37bd2b4fe148a45806af) @@ -121,6 +121,23 @@ Assert.AreSame(calculation.Output, output); } + [Test] + public void ToString_Always_ReturnName() + { + // Setup + var expectedName = "someTestName"; + var calculation = new ClosingStructuresCalculation + { + Name = expectedName + }; + + // Call + var result = calculation.ToString(); + + // Assert + Assert.AreEqual(expectedName, result); + } + private class TestClosingStructuresOutput : ProbabilityAssessmentOutput { public TestClosingStructuresOutput() : base(0, 0, 0, 0, 0) {} Index: Ringtoets/ClosingStructures/test/Ringtoets.ClosingStructures.Forms.Test/Views/ClosingStructuresScenariosViewTest.cs =================================================================== diff -u -r9fffdfe86ac1685eb9369e2190c26181e3613cb1 -r93baa4ee308eff5a157e37bd2b4fe148a45806af --- Ringtoets/ClosingStructures/test/Ringtoets.ClosingStructures.Forms.Test/Views/ClosingStructuresScenariosViewTest.cs (.../ClosingStructuresScenariosViewTest.cs) (revision 9fffdfe86ac1685eb9369e2190c26181e3613cb1) +++ Ringtoets/ClosingStructures/test/Ringtoets.ClosingStructures.Forms.Test/Views/ClosingStructuresScenariosViewTest.cs (.../ClosingStructuresScenariosViewTest.cs) (revision 93baa4ee308eff5a157e37bd2b4fe148a45806af) @@ -20,13 +20,17 @@ // All rights reserved. using System.Drawing; +using System.Linq; using System.Windows.Forms; +using Core.Common.Base.Geometry; +using Core.Common.Controls.DataGrid; using Core.Common.Controls.Views; using NUnit.Extensions.Forms; using NUnit.Framework; using Ringtoets.ClosingStructures.Data; using Ringtoets.ClosingStructures.Forms.Views; using Ringtoets.Common.Data.Calculation; +using Ringtoets.Common.Data.FailureMechanism; using Ringtoets.Common.Forms; namespace Ringtoets.ClosingStructures.Forms.Test.Views @@ -100,6 +104,253 @@ } } + [Test] + public void Data_WithFailureMechanism_UpdateScenarioControl() + { + // Setup + using (var view = ShowScenariosView()) + { + var failureMechanism = CreateCompleteFailureMechanism(); + view.FailureMechanism = failureMechanism; + + // Call + view.Data = failureMechanism.CalculationsGroup; + + // Assert + AssertDataGridView(failureMechanism, false, new[] + { + new [] { "", "CalculationA"}, + new [] { "", "CalculationB"} + }); + } + } + + [Test] + public void Data_SetToNullAfterGridViewShowsData_ClearsScenarioControl() + { + // Setup + using (var view = ShowScenariosView()) + { + var failureMechanism = CreateCompleteFailureMechanism(); + view.FailureMechanism = failureMechanism; + view.Data = failureMechanism.CalculationsGroup; + + // Call + view.Data = null; + + // Assert + AssertDataGridView(failureMechanism, true); + } + } + + [Test] + public void FailureMechanism_WithData_UpdateScenarioControl() + { + // Setup + using (var view = ShowScenariosView()) + { + var failureMechanism = CreateCompleteFailureMechanism(); + view.Data = failureMechanism.CalculationsGroup; + + // Call + view.FailureMechanism = failureMechanism; + + // Assert + AssertDataGridView(failureMechanism, false, new[] + { + new [] { "", "CalculationA"}, + new [] { "", "CalculationB"} + }); + } + } + + [Test] + public void FailureMechanism_WithoutData_ClearsScenarioControl() + { + // Setup + using (var view = ShowScenariosView()) + { + var failureMechanism = CreateCompleteFailureMechanism(); + view.Data = failureMechanism.CalculationsGroup; + view.FailureMechanism = failureMechanism; + + // Call + view.FailureMechanism = null; + + // Assert + AssertDataGridView(failureMechanism, true); + } + } + + [Test] + public void NotifyFailureMechanism_SectionsAddedAfterFullInitialization_NewRowAddedToView() + { + // Setup + using (var view = ShowScenariosView()) + { + var failureMechanism = CreateCompleteFailureMechanism(); + view.Data = failureMechanism.CalculationsGroup; + view.FailureMechanism = failureMechanism; + + view.FailureMechanism.AddSection(new FailureMechanismSection("SectionC", new[] + { + view.FailureMechanism.Sections.Last().GetLast(), new Point2D(30,30) + })); + + // Call + failureMechanism.NotifyObservers(); + + // Assert + AssertDataGridView(failureMechanism, false, new[] + { + new [] { "", "CalculationA"}, + new [] { "", "CalculationB"}, + new [] { ""} + }); + } + } + + [Test] + public void NotifyCalculation_CalculationChangedDikeProfile_CalculationMovedToOtherSectionResultOptions() + { + // Setup + using (var view = ShowScenariosView()) + { + var failureMechanism = CreateCompleteFailureMechanism(); + view.Data = failureMechanism.CalculationsGroup; + view.FailureMechanism = failureMechanism; + + var calculationA = (ClosingStructuresCalculation)failureMechanism.CalculationsGroup.Children[0]; + var calculationB = (ClosingStructuresCalculation)failureMechanism.CalculationsGroup.Children[1]; + + calculationA.InputParameters.Structure = calculationB.InputParameters.Structure; + + // Call + calculationA.NotifyObservers(); + + // Assert + AssertDataGridView(failureMechanism, false, new[] + { + new [] { ""}, + new [] { "", "CalculationA", "CalculationB"}, + }); + } + } + + [Test] + public void NotifyCalculationGroup_CalculationAdded_CalculationAddedToSectionResultOptions() + { + // Setup + using (var view = ShowScenariosView()) + { + var failureMechanism = CreateCompleteFailureMechanism(); + view.Data = failureMechanism.CalculationsGroup; + view.FailureMechanism = failureMechanism; + + var calculationB = ((ClosingStructuresCalculation)failureMechanism.CalculationsGroup.Children[1]); + var calculationC = new ClosingStructuresCalculation + { + Name = "CalculationC", + InputParameters = + { + Structure = calculationB.InputParameters.Structure + } + }; + failureMechanism.CalculationsGroup.Children.Add(calculationC); + + calculationC.InputParameters.Structure = calculationC.InputParameters.Structure; + + // Call + failureMechanism.CalculationsGroup.NotifyObservers(); + + // Assert + AssertDataGridView(failureMechanism, false, new[] + { + new [] { "", "CalculationA"}, + new [] { "", "CalculationB", "CalculationC"}, + }); + } + } + + private void AssertDataGridView( + ClosingStructuresFailureMechanism failureMechanism, + bool shouldBeCleared, + string[][] expectedComboBoxItemTexts = null) + { + var dataGridView = (DataGridView)new ControlTester("dataGridView").TheObject; + var rowCount = dataGridView.RowCount; + + if (shouldBeCleared) + { + Assert.AreEqual(0, rowCount); + } + else + { + var dataGridViewColumn = (DataGridViewComboBoxColumn)dataGridView.Columns[1]; + + Assert.AreEqual(failureMechanism.SectionResults.Count(), rowCount); + Assert.AreEqual(failureMechanism.Calculations.Count(), dataGridViewColumn.Items.Count); + + for (int i = 0; i < rowCount; i++ ) + { + var cell = (DataGridViewComboBoxCell)dataGridView[1, i]; + var items = cell.Items.OfType>(); + Assert.AreEqual(expectedComboBoxItemTexts[i], items.Select(r => r.DisplayName)); + } + } + } + + private ClosingStructuresFailureMechanism CreateCompleteFailureMechanism() + { + ClosingStructuresFailureMechanism failureMechanism = new ClosingStructuresFailureMechanism(); + var matchingPointA = new Point2D(0, 0); + var matchingPointB = new Point2D(20, 20); + var calculationA = new ClosingStructuresCalculation + { + Name = "CalculationA", + InputParameters = + { + Structure = CreateStructure(matchingPointA) + } + }; + var calculationB = new ClosingStructuresCalculation + { + Name = "CalculationB", + InputParameters = + { + Structure = CreateStructure(matchingPointB) + } + }; + Point2D connectionPoint = new Point2D(10, 10); + var failureMechanismSectionA = new FailureMechanismSection("sectionA", new[] + { + matchingPointA, + connectionPoint + }); + var failureMechanismSectionB = new FailureMechanismSection("sectionB", new[] + { + connectionPoint, + matchingPointB + }); + + failureMechanism.CalculationsGroup.Children.Add(calculationA); + failureMechanism.CalculationsGroup.Children.Add(calculationB); + failureMechanism.AddSection(failureMechanismSectionA); + failureMechanism.AddSection(failureMechanismSectionB); + + return failureMechanism; + } + + private ClosingStructure CreateStructure(Point2D location) + { + return new ClosingStructure(new ClosingStructure.ConstructionProperties + { + Id = "1", + Name = "", + Location = location + }); + } + private ClosingStructuresScenariosView ShowScenariosView() { var scenariosView = new ClosingStructuresScenariosView(); Index: Ringtoets/GrassCoverErosionInwards/src/Ringtoets.GrassCoverErosionInwards.Forms/Views/GrassCoverErosionInwardsScenariosView.cs =================================================================== diff -u -r04e2ad28172dab2091ef18840dfc0ba77c6c0c7d -r93baa4ee308eff5a157e37bd2b4fe148a45806af --- Ringtoets/GrassCoverErosionInwards/src/Ringtoets.GrassCoverErosionInwards.Forms/Views/GrassCoverErosionInwardsScenariosView.cs (.../GrassCoverErosionInwardsScenariosView.cs) (revision 04e2ad28172dab2091ef18840dfc0ba77c6c0c7d) +++ Ringtoets/GrassCoverErosionInwards/src/Ringtoets.GrassCoverErosionInwards.Forms/Views/GrassCoverErosionInwardsScenariosView.cs (.../GrassCoverErosionInwardsScenariosView.cs) (revision 93baa4ee308eff5a157e37bd2b4fe148a45806af) @@ -120,19 +120,19 @@ { scenarioSelectionControl.EndEdit(); - if (FailureMechanism == null || FailureMechanism.SectionResults == null || data == null || data.Children == null) + if (failureMechanism == null || failureMechanism.SectionResults == null || data == null || data.Children == null) { scenarioSelectionControl.ClearDataSource(); } else { - var calculations = data.GetCalculations(); + var calculations = data.GetCalculations().ToArray(); Dictionary> calculationsPerSegment = GrassCoverErosionInwardsHelper.CollectCalculationsPerSection(failureMechanism.Sections, calculations.OfType()); List scenarioRows = - FailureMechanism.SectionResults.Select(sectionResult => new GrassCoverErosionInwardsScenarioRow(sectionResult)).ToList(); + failureMechanism.SectionResults.Select(sectionResult => new GrassCoverErosionInwardsScenarioRow(sectionResult)).ToList(); scenarioSelectionControl.UpdateDataGridViewDataSource(calculations, scenarioRows, calculationsPerSegment); }