Fisheye: Tag 6d42ac47e4307f7c8b2abcd473bdb5189e30697a refers to a dead (removed) revision in file `Riskeer/Common/src/Riskeer.Common.Forms/Views/CalculationRow.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d42ac47e4307f7c8b2abcd473bdb5189e30697a refers to a dead (removed) revision in file `Riskeer/Common/src/Riskeer.Common.Forms/Views/CalculationsView.Designer.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d42ac47e4307f7c8b2abcd473bdb5189e30697a refers to a dead (removed) revision in file `Riskeer/Common/src/Riskeer.Common.Forms/Views/CalculationsView.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 6d42ac47e4307f7c8b2abcd473bdb5189e30697a refers to a dead (removed) revision in file `Riskeer/Common/src/Riskeer.Common.Forms/Views/CalculationsView.resx'. Fisheye: No comparison available. Pass `N' to diff? Index: Riskeer/Piping/src/Riskeer.Piping.Forms/Riskeer.Piping.Forms.csproj =================================================================== diff -u -r653147ae92ff1a7759f7683afe28de029ae7a0be -r6d42ac47e4307f7c8b2abcd473bdb5189e30697a --- Riskeer/Piping/src/Riskeer.Piping.Forms/Riskeer.Piping.Forms.csproj (.../Riskeer.Piping.Forms.csproj) (revision 653147ae92ff1a7759f7683afe28de029ae7a0be) +++ Riskeer/Piping/src/Riskeer.Piping.Forms/Riskeer.Piping.Forms.csproj (.../Riskeer.Piping.Forms.csproj) (revision 6d42ac47e4307f7c8b2abcd473bdb5189e30697a) @@ -60,6 +60,9 @@ True Resources.resx + + UserControl + Index: Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationRow.cs =================================================================== diff -u --- Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationRow.cs (revision 0) +++ Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationRow.cs (revision 6d42ac47e4307f7c8b2abcd473bdb5189e30697a) @@ -0,0 +1,122 @@ +// Copyright (C) Stichting Deltares 2021. 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 Core.Common.Base.Geometry; +using Core.Common.Controls.DataGrid; +using Riskeer.Common.Data.Calculation; +using Riskeer.Common.Data.Hydraulics; +using Riskeer.Common.Forms.ChangeHandlers; +using Riskeer.Common.Forms.PresentationObjects; +using Riskeer.Common.Forms.PropertyClasses; + +namespace Riskeer.Piping.Forms.Views +{ + /// + /// This class represents a row of in the . + /// + /// The type of the calculation. + public abstract class CalculationRow + where TCalculation : class, ICalculation + { + /// + /// Creates a new instance of . + /// + /// The this row contains. + /// The handler responsible for handling effects of a property change. + /// Thrown when any parameter is null. + protected CalculationRow(TCalculation calculation, IObservablePropertyChangeHandler propertyChangeHandler) + { + if (calculation == null) + { + throw new ArgumentNullException(nameof(calculation)); + } + + if (propertyChangeHandler == null) + { + throw new ArgumentNullException(nameof(propertyChangeHandler)); + } + + Calculation = calculation; + PropertyChangeHandler = propertyChangeHandler; + } + + /// + /// Gets the this row contains. + /// + public TCalculation Calculation { get; } + + /// + /// Gets or sets the name of the . + /// + public string Name + { + get => Calculation.Name; + set + { + Calculation.Name = value; + Calculation.NotifyObservers(); + } + } + + /// + /// Gets or sets the hydraulic boundary location of the . + /// + public DataGridViewComboBoxItemWrapper SelectableHydraulicBoundaryLocation + { + get + { + if (HydraulicBoundaryLocation == null) + { + return new DataGridViewComboBoxItemWrapper(null); + } + + return new DataGridViewComboBoxItemWrapper( + new SelectableHydraulicBoundaryLocation(HydraulicBoundaryLocation, + GetCalculationLocation())); + } + set + { + HydraulicBoundaryLocation valueToSet = value?.WrappedObject?.HydraulicBoundaryLocation; + if (!ReferenceEquals(HydraulicBoundaryLocation, valueToSet)) + { + PropertyChangeHelper.ChangePropertyAndNotify(() => HydraulicBoundaryLocation = valueToSet, PropertyChangeHandler); + } + } + } + + /// + /// Gets the location of the . + /// + /// The location of the . + public abstract Point2D GetCalculationLocation(); + + /// + /// Gets the . + /// + protected IObservablePropertyChangeHandler PropertyChangeHandler { get; } + + /// + /// Gets or sets the of the . + /// + protected abstract HydraulicBoundaryLocation HydraulicBoundaryLocation { get; set; } + } +} \ No newline at end of file Index: Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.Designer.cs =================================================================== diff -u --- Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.Designer.cs (revision 0) +++ Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.Designer.cs (revision 6d42ac47e4307f7c8b2abcd473bdb5189e30697a) @@ -0,0 +1,195 @@ +// Copyright (C) Stichting Deltares 2021. 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. + +namespace Riskeer.Piping.Forms.Views +{ + partial class CalculationsView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.listBox = new System.Windows.Forms.ListBox(); + this.sectionsLabel = new System.Windows.Forms.Label(); + this.dataGridTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); + this.dataGridViewControl = new Core.Common.Controls.DataGrid.DataGridViewControl(); + this.calculationsLabel = new System.Windows.Forms.Label(); + this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); + this.generateButton = new Core.Common.Controls.Forms.EnhancedButton(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.dataGridTableLayoutPanel.SuspendLayout(); + this.tableLayoutPanel.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer + // + this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer.Location = new System.Drawing.Point(3, 3); + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add(this.listBox); + this.splitContainer.Panel1.Controls.Add(this.sectionsLabel); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.dataGridTableLayoutPanel); + this.splitContainer.Panel2.Controls.Add(this.calculationsLabel); + this.splitContainer.Size = new System.Drawing.Size(1343, 598); + this.splitContainer.SplitterDistance = 250; + this.splitContainer.TabIndex = 0; + // + // listBox + // + this.listBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.listBox.FormattingEnabled = true; + this.listBox.Location = new System.Drawing.Point(0, 13); + this.listBox.Name = "listBox"; + this.listBox.Size = new System.Drawing.Size(250, 585); + this.listBox.TabIndex = 1; + // + // sectionsLabel + // + this.sectionsLabel.AutoSize = true; + this.sectionsLabel.Dock = System.Windows.Forms.DockStyle.Top; + this.sectionsLabel.Location = new System.Drawing.Point(0, 0); + this.sectionsLabel.Name = "sectionsLabel"; + this.sectionsLabel.Size = new System.Drawing.Size(26, 13); + this.sectionsLabel.TabIndex = 0; + this.sectionsLabel.Text = "Vak"; + // + // dataGridTableLayoutPanel + // + this.dataGridTableLayoutPanel.ColumnCount = 1; + this.dataGridTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.dataGridTableLayoutPanel.Controls.Add(this.dataGridViewControl, 0, 0); + this.dataGridTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.dataGridTableLayoutPanel.Location = new System.Drawing.Point(0, 13); + this.dataGridTableLayoutPanel.Name = "dataGridTableLayoutPanel"; + this.dataGridTableLayoutPanel.RowCount = 1; + this.dataGridTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.dataGridTableLayoutPanel.Size = new System.Drawing.Size(1089, 585); + this.dataGridTableLayoutPanel.TabIndex = 1; + // + // dataGridViewControl + // + this.dataGridViewControl.Dock = System.Windows.Forms.DockStyle.Fill; + this.dataGridViewControl.Location = new System.Drawing.Point(3, 3); + this.dataGridViewControl.MultiSelect = true; + this.dataGridViewControl.Name = "dataGridViewControl"; + this.dataGridViewControl.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.RowHeaderSelect; + this.dataGridViewControl.Size = new System.Drawing.Size(1083, 579); + this.dataGridViewControl.TabIndex = 0; + // + // calculationsLabel + // + this.calculationsLabel.AutoSize = true; + this.calculationsLabel.Dock = System.Windows.Forms.DockStyle.Top; + this.calculationsLabel.Location = new System.Drawing.Point(0, 0); + this.calculationsLabel.Name = "calculationsLabel"; + this.calculationsLabel.Size = new System.Drawing.Size(182, 13); + this.calculationsLabel.TabIndex = 0; + this.calculationsLabel.Text = "Berekeningen voor geselecteerd vak"; + // + // tableLayoutPanel + // + this.tableLayoutPanel.ColumnCount = 1; + this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel.Controls.Add(this.splitContainer, 0, 0); + this.tableLayoutPanel.Controls.Add(this.generateButton, 0, 1); + this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel.Name = "tableLayoutPanel"; + this.tableLayoutPanel.RowCount = 2; + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel.Size = new System.Drawing.Size(1349, 644); + this.tableLayoutPanel.TabIndex = 0; + // + // generateButton + // + this.generateButton.Location = new System.Drawing.Point(3, 607); + this.generateButton.Name = "generateButton"; + this.generateButton.Padding = new System.Windows.Forms.Padding(2); + this.generateButton.Size = new System.Drawing.Size(170, 34); + this.generateButton.TabIndex = 1; + this.generateButton.Text = global::Riskeer.Common.Forms.Properties.Resources.CalculationGroup_Generate_calculations; + this.generateButton.UseVisualStyleBackColor = true; + this.generateButton.Click += new System.EventHandler(this.generateButton_Click); + // + // CalculationsView + // + this.Controls.Add(this.tableLayoutPanel); + this.Name = "CalculationsView"; + this.Size = new System.Drawing.Size(1349, 644); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel1.PerformLayout(); + this.splitContainer.Panel2.ResumeLayout(false); + this.splitContainer.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.dataGridTableLayoutPanel.ResumeLayout(false); + this.tableLayoutPanel.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer; + private System.Windows.Forms.ListBox listBox; + private System.Windows.Forms.Label sectionsLabel; + private System.Windows.Forms.Label calculationsLabel; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; + private System.Windows.Forms.TableLayoutPanel dataGridTableLayoutPanel; + private Core.Common.Controls.DataGrid.DataGridViewControl dataGridViewControl; + private Core.Common.Controls.Forms.EnhancedButton generateButton; + + protected System.Windows.Forms.TableLayoutPanel DataGridTableLayoutPanel + { + get => this.dataGridTableLayoutPanel; + } + + protected Core.Common.Controls.Forms.EnhancedButton GenerateButton + { + get => this.generateButton; + } + + protected Core.Common.Controls.DataGrid.DataGridViewControl DataGridViewControl + { + get => this.dataGridViewControl; + } + } +} Index: Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.cs =================================================================== diff -u --- Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.cs (revision 0) +++ Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.cs (revision 6d42ac47e4307f7c8b2abcd473bdb5189e30697a) @@ -0,0 +1,501 @@ +// Copyright (C) Stichting Deltares 2021. 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.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using Core.Common.Base; +using Core.Common.Base.Geometry; +using Core.Common.Controls.DataGrid; +using Core.Common.Controls.Views; +using Core.Common.Util.Extensions; +using Riskeer.Common.Data.AssessmentSection; +using Riskeer.Common.Data.Calculation; +using Riskeer.Common.Data.FailureMechanism; +using Riskeer.Common.Forms.Helpers; +using Riskeer.Common.Forms.PresentationObjects; +using Riskeer.Common.Forms.Properties; +using Riskeer.Common.Forms.Views; +using Riskeer.Piping.Data; + +namespace Riskeer.Piping.Forms.Views +{ + /// + /// Base view for configuring calculations. + /// + /// The type of calculation. + /// The type of the calculation input. + /// The type of the calculation row. + /// The type of the failure mechanism. + public abstract partial class CalculationsView : UserControl, ISelectionProvider, IView + where TCalculation : class, ICalculation + where TCalculationRow : CalculationRow + where TCalculationInput : class, ICalculationInput + where TFailureMechanism : PipingFailureMechanism + { + private int nameColumnIndex = -1; + private int selectableHydraulicBoundaryLocationColumnIndex = -1; + + private Observer failureMechanismObserver; + private Observer hydraulicBoundaryLocationsObserver; + private RecursiveObserver inputObserver; + private RecursiveObserver calculationObserver; + private RecursiveObserver calculationGroupObserver; + + private CalculationGroup calculationGroup; + + private List dataSource; + + public event EventHandler SelectionChanged; + + /// + /// Creates a new instance of . + /// + /// All the calculations of the failure mechanism. + /// The the calculations belongs to. + /// The the calculations belong to. + /// Thrown when any parameter is null. + protected CalculationsView(CalculationGroup calculationGroup, TFailureMechanism failureMechanism, IAssessmentSection assessmentSection) + { + if (calculationGroup == null) + { + throw new ArgumentNullException(nameof(calculationGroup)); + } + + if (failureMechanism == null) + { + throw new ArgumentNullException(nameof(failureMechanism)); + } + + if (assessmentSection == null) + { + throw new ArgumentNullException(nameof(assessmentSection)); + } + + this.calculationGroup = calculationGroup; + FailureMechanism = failureMechanism; + AssessmentSection = assessmentSection; + + InitializeComponent(); + + InitializeListBox(); + InitializeDataGridView(); + + UpdateSectionsListBox(); + } + + public object Selection + { + get + { + DataGridViewRow currentRow = DataGridViewControl.CurrentRow; + return currentRow != null ? CreateSelectedItemFromCurrentRow((TCalculationRow) currentRow.DataBoundItem) : null; + } + } + + public object Data + { + get => calculationGroup; + set => calculationGroup = value as CalculationGroup; + } + + /// + /// Gets the failure mechanism. + /// + protected TFailureMechanism FailureMechanism { get; } + + /// + /// Gets the assessment section. + /// + protected IAssessmentSection AssessmentSection { get; } + + /// + /// Gets the selected failure mechanism section. + /// + protected FailureMechanismSection SelectedFailureMechanismSection => listBox.SelectedItem as FailureMechanismSection; + + /// + /// Gets an indicator whether the view is loaded. + /// + protected bool Loaded { get; private set; } + + protected override void OnLoad(EventArgs e) + { + InitializeObservers(); + + // Necessary to correctly load the content of the dropdown lists of the comboboxes... + UpdateDataGridViewDataSource(); + + base.OnLoad(e); + + UpdateGenerateCalculationsButtonState(); + + Loaded = true; + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (Loaded) + { + failureMechanismObserver.Dispose(); + inputObserver.Dispose(); + calculationObserver.Dispose(); + calculationGroupObserver.Dispose(); + hydraulicBoundaryLocationsObserver.Dispose(); + } + + components?.Dispose(); + + Loaded = false; + } + + base.Dispose(disposing); + } + + /// + /// Creates the selected item based on the current row. + /// + /// The currently selected row in the . + /// The selected item. + protected abstract object CreateSelectedItemFromCurrentRow(TCalculationRow currentRow); + + /// + /// Gets all reference locations. + /// + /// The reference locations. + protected abstract IEnumerable GetReferenceLocations(); + + /// + /// Determines whether the intersects with a section. + /// + /// The calculation to check. + /// The line segments of the section. + /// true when the intersects + /// with the ; false otherwise. + protected abstract bool IsCalculationIntersectionWithReferenceLineInSection(TCalculation calculation, IEnumerable lineSegments); + + /// + /// Creates a with the given . + /// + /// The to create the row for. + /// The created . + protected abstract TCalculationRow CreateRow(TCalculation calculation); + + /// + /// Gets an indicator whether calculations can be generated. + /// + /// true when calculations can be generated; false otherwise. + protected abstract bool CanGenerateCalculations(); + + /// + /// Generates the calculations. + /// + protected abstract void GenerateCalculations(); + + /// + /// Initializes the columns + /// + /// Thrown when one of the generic columns is not added via . + protected virtual void InitializeDataGridView() + { + DataGridViewControl.CurrentRowChanged += DataGridViewOnCurrentRowChangedHandler; + + AddColumns(() => nameColumnIndex = DataGridViewControl.AddTextBoxColumn( + nameof(CalculationRow.Name), + Resources.FailureMechanism_Name_DisplayName), + () => selectableHydraulicBoundaryLocationColumnIndex = DataGridViewControl.AddComboBoxColumn>( + nameof(CalculationRow.SelectableHydraulicBoundaryLocation), + Resources.HydraulicBoundaryLocation_DisplayName, + null, + nameof(DataGridViewComboBoxItemWrapper.This), + nameof(DataGridViewComboBoxItemWrapper.DisplayName))); + + if (nameColumnIndex == -1 || selectableHydraulicBoundaryLocationColumnIndex == -1) + { + throw new InvalidOperationException("Both the name column and the hydraulic boundary database column need to be added to the data grid view."); + } + } + + /// + /// Adds the columns to the data grid view. + /// + /// Action for adding the name column (which is mandatory). + /// Action for adding the hydraulic boundary database column (which is mandatory). + protected abstract void AddColumns(Action addNameColumn, Action addHydraulicBoundaryLocationColumn); + + /// + /// Initializes the observers. + /// + protected virtual void InitializeObservers() + { + failureMechanismObserver = new Observer(UpdateSectionsListBox) + { + Observable = FailureMechanism + }; + hydraulicBoundaryLocationsObserver = new Observer(() => + { + PrefillComboBoxListItemsAtColumnLevel(); + UpdateComboBoxColumns(); + }) + { + Observable = AssessmentSection.HydraulicBoundaryDatabase.Locations + }; + + // The concat is needed to observe the input of calculations in child groups. + inputObserver = new RecursiveObserver(() => UpdateDataGridViewDataSource(), pcg => pcg.Children.Concat(pcg.Children.OfType().Select(pc => pc.InputParameters))) + { + Observable = calculationGroup + }; + calculationObserver = new RecursiveObserver(() => DataGridViewControl.RefreshDataGridView(), pcg => pcg.Children) + { + Observable = calculationGroup + }; + calculationGroupObserver = new RecursiveObserver(() => UpdateDataGridViewDataSource(), pcg => pcg.Children) + { + Observable = calculationGroup + }; + } + + /// + /// Updates the state of the generate calculations button. + /// + protected void UpdateGenerateCalculationsButtonState() + { + GenerateButton.Enabled = CanGenerateCalculations(); + } + + /// + /// Sets the items on the . + /// + /// The collection to set the items on. + /// The item to set on the collection. + protected static void SetItemsOnObjectCollection(DataGridViewComboBoxCell.ObjectCollection objectCollection, object[] comboBoxItems) + { + objectCollection.Clear(); + objectCollection.AddRange(comboBoxItems); + } + + /// + /// Updates the columns. + /// + protected virtual void UpdateComboBoxColumns() + { + UpdateSelectableHydraulicBoundaryLocationsColumn(); + } + + #region Prefill combo box list items + + /// + /// Pre fills the list items. + /// + protected virtual void PrefillComboBoxListItemsAtColumnLevel() + { + var selectableHydraulicBoundaryLocationColumn = (DataGridViewComboBoxColumn) DataGridViewControl.GetColumnFromIndex(selectableHydraulicBoundaryLocationColumnIndex); + + // Need to prefill for all possible data in order to guarantee 'combo box' columns + // do not generate errors when their cell value is not present in the list of available + // items. + using (new SuspendDataGridViewColumnResizes(selectableHydraulicBoundaryLocationColumn)) + { + SetItemsOnObjectCollection(selectableHydraulicBoundaryLocationColumn.Items, + GetSelectableHydraulicBoundaryLocationsDataSource(GetSelectableHydraulicBoundaryLocationsFromFailureMechanism())); + } + } + + #endregion + + /// + /// Updates the data source of the data grid view. + /// + /// Whether or not to skip changes coming from the calculation view itself. + protected void UpdateDataGridViewDataSource(bool skipChangesComingFromView = true) + { + if (skipChangesComingFromView && DataGridViewControl.IsCurrentCellInEditMode) + { + DataGridViewControl.AutoResizeColumns(); + + FormatRowWithColumnStateDefinitions(DataGridViewControl.CurrentRow); + + return; + } + + dataSource?.ForEachElementDo(UnsubscribeFromCalculationRow); + + if (!(listBox.SelectedItem is FailureMechanismSection failureMechanismSection)) + { + dataSource = null; + DataGridViewControl.SetDataSource(null); + return; + } + + IEnumerable lineSegments = Math2D.ConvertPointsToLineSegments(failureMechanismSection.Points); + IEnumerable calculations = calculationGroup + .GetCalculations() + .OfType() + .Where(cs => IsCalculationIntersectionWithReferenceLineInSection(cs, lineSegments)); + + PrefillComboBoxListItemsAtColumnLevel(); + + dataSource = calculations.Select(CreateRow).ToList(); + DataGridViewControl.SetDataSource(dataSource); + DataGridViewControl.ClearCurrentCell(); + + UpdateComboBoxColumns(); + + FormatGridWithColumnStateDefinitions(); + + dataSource.ForEachElementDo(SubscribeToCalculationRow); + } + + /// + /// Handle for subscribing to all individual calculation rows in the view. + /// + /// The specific calculation row to subscribe to. + protected virtual void SubscribeToCalculationRow(TCalculationRow calculationRow) {} + + /// + /// Handle for unsubscribing from all individual calculation rows in the view. + /// + /// The specific calculation row to unsubscribe from. + protected virtual void UnsubscribeFromCalculationRow(TCalculationRow calculationRow) {} + + private void InitializeListBox() + { + listBox.DisplayMember = nameof(FailureMechanismSection.Name); + listBox.SelectedValueChanged += ListBoxOnSelectedValueChanged; + } + + private void UpdateSectionsListBox() + { + listBox.Items.Clear(); + + if (FailureMechanism.Sections.Any()) + { + listBox.Items.AddRange(FailureMechanism.Sections.Cast().ToArray()); + listBox.SelectedItem = FailureMechanism.Sections.First(); + } + } + + private void FormatGridWithColumnStateDefinitions() + { + foreach (DataGridViewRow row in DataGridViewControl.Rows) + { + FormatRowWithColumnStateDefinitions(row); + } + } + + private void FormatRowWithColumnStateDefinitions(DataGridViewRow row) + { + foreach (DataGridViewCell cell in row.Cells) + { + DataGridViewControl.FormatCellWithColumnStateDefinition(cell.RowIndex, cell.ColumnIndex); + } + } + + #region HydraulicBoundaryLocations + + private void UpdateSelectableHydraulicBoundaryLocationsColumn() + { + var column = (DataGridViewComboBoxColumn) DataGridViewControl.GetColumnFromIndex(selectableHydraulicBoundaryLocationColumnIndex); + + using (new SuspendDataGridViewColumnResizes(column)) + { + foreach (DataGridViewRow dataGridViewRow in DataGridViewControl.Rows) + { + FillAvailableSelectableHydraulicBoundaryLocationsList(dataGridViewRow); + } + } + } + + private void FillAvailableSelectableHydraulicBoundaryLocationsList(DataGridViewRow dataGridViewRow) + { + var rowData = (TCalculationRow) dataGridViewRow.DataBoundItem; + IEnumerable locations = GetSelectableHydraulicBoundaryLocations(rowData.GetCalculationLocation()); + + var cell = (DataGridViewComboBoxCell) dataGridViewRow.Cells[selectableHydraulicBoundaryLocationColumnIndex]; + DataGridViewComboBoxItemWrapper[] dataGridViewComboBoxItemWrappers = GetSelectableHydraulicBoundaryLocationsDataSource(locations); + SetItemsOnObjectCollection(cell.Items, dataGridViewComboBoxItemWrappers); + } + + private IEnumerable GetSelectableHydraulicBoundaryLocationsFromFailureMechanism() + { + var selectableHydraulicBoundaryLocations = new List(); + + foreach (Point2D referenceLocation in GetReferenceLocations()) + { + selectableHydraulicBoundaryLocations.AddRange(GetSelectableHydraulicBoundaryLocations(referenceLocation)); + } + + return selectableHydraulicBoundaryLocations; + } + + private static DataGridViewComboBoxItemWrapper[] GetSelectableHydraulicBoundaryLocationsDataSource( + IEnumerable selectableHydraulicBoundaryLocations = null) + { + var dataGridViewComboBoxItemWrappers = new List> + { + new DataGridViewComboBoxItemWrapper(null) + }; + + if (selectableHydraulicBoundaryLocations != null) + { + dataGridViewComboBoxItemWrappers.AddRange(selectableHydraulicBoundaryLocations.Select(hbl => new DataGridViewComboBoxItemWrapper(hbl))); + } + + return dataGridViewComboBoxItemWrappers.ToArray(); + } + + private IEnumerable GetSelectableHydraulicBoundaryLocations(Point2D referencePoint) + { + return SelectableHydraulicBoundaryLocationHelper.GetSortedSelectableHydraulicBoundaryLocations( + AssessmentSection.HydraulicBoundaryDatabase.Locations, referencePoint); + } + + #endregion + + #region Event handling + + private void DataGridViewOnCurrentRowChangedHandler(object sender, EventArgs e) + { + OnSelectionChanged(); + } + + private void OnSelectionChanged() + { + SelectionChanged?.Invoke(this, new EventArgs()); + } + + private void ListBoxOnSelectedValueChanged(object sender, EventArgs e) + { + UpdateDataGridViewDataSource(); + } + + private void generateButton_Click(object sender, EventArgs e) + { + GenerateCalculations(); + } + + #endregion + } +} \ No newline at end of file Index: Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.resx =================================================================== diff -u --- Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.resx (revision 0) +++ Riskeer/Piping/src/Riskeer.Piping.Forms/Views/CalculationsView.resx (revision 6d42ac47e4307f7c8b2abcd473bdb5189e30697a) @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file