// 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.Linq; using System.Windows.Forms; using Core.Common.Controls.Views; using Core.Common.Util.Extensions; using Ringtoets.Common.Data.AssessmentSection; using Ringtoets.Common.Data.IllustrationPoints; using Ringtoets.Common.Forms.PresentationObjects; using Ringtoets.Common.Forms.Properties; namespace Ringtoets.Common.Forms.Views { /// /// Base view for selecting locations and starting calculation for said objects. /// /// The type of the location object. public abstract partial class LocationsView : UserControl, ISelectionProvider, IView where T : class { private const int calculateColumnIndex = 0; private bool suspendAllEvents; private bool suspendIllustrationPointsControlSelectionChanges; public event EventHandler SelectionChanged; /// /// Creates a new instance of . /// protected LocationsView() { InitializeComponent(); LocalizeControls(); InitializeEventHandlers(); } /// /// Gets or sets the . /// public IAssessmentSection AssessmentSection { get; protected set; } public object Selection { get; private set; } public abstract object Data { get; set; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); InitializeDataGridView(); } /// /// Updates the data source of the data table based on the . /// protected void UpdateDataGridViewDataSource() { suspendAllEvents = true; SetDataSource(); illustrationPointsControl.Data = GetIllustrationPointControlItems(); suspendAllEvents = false; UpdateCalculateForSelectedButton(); ProvideLocationSelection(); } /// /// Initializes the . /// protected virtual void InitializeDataGridView() { dataGridViewControl.AddCheckBoxColumn(nameof(CalculatableRow.ShouldCalculate), Resources.CalculatableView_Calculate); } /// /// Creates a new object that is used as the object for from /// the currently selected row in the data table. /// /// The newly created object. protected abstract object CreateSelectedItemFromCurrentRow(); /// /// Sets the datasource on the . /// protected abstract void SetDataSource(); /// /// Handles the calculation routine for the currently selected rows. /// protected abstract void CalculateForSelectedRows(); /// /// Gets all the row items from the . /// protected IEnumerable> GetCalculatableRows() { return dataGridViewControl.Rows .Cast() .Select(row => (CalculatableRow) row.DataBoundItem) .ToArray(); } /// /// Gets all the selected calculatable objects. /// protected IEnumerable GetSelectedCalculatableObjects() { return GetCalculatableRows().Where(r => r.ShouldCalculate) .Select(r => r.CalculatableObject) .ToArray(); } /// /// Validates the calculatable objects. /// /// A validation message in case no calculations can be performed, null otherwise. protected virtual string ValidateCalculatableObjects() { if (!GetCalculatableRows().Any(r => r.ShouldCalculate)) { return Resources.CalculatableViews_No_calculations_selected; } return null; } /// /// Updates the state of the calculation button and the corresponding error provider. /// protected void UpdateCalculateForSelectedButton() { string validationText = ValidateCalculatableObjects(); if (!string.IsNullOrEmpty(validationText)) { CalculateForSelectedButton.Enabled = false; CalculateForSelectedButtonErrorProvider.SetError(CalculateForSelectedButton, validationText); } else { CalculateForSelectedButton.Enabled = true; CalculateForSelectedButtonErrorProvider.SetError(CalculateForSelectedButton, ""); } } /// /// Handles the update from the hydraulic boundary database by refreshing /// the data grid view and updating the data of the illustration points control. /// protected void HandleHydraulicBoundaryDatabaseUpdate() { suspendAllEvents = true; dataGridViewControl.RefreshDataGridView(); HandlePossibleOutdatedIllustrationPointsControl(); suspendAllEvents = false; HandlePossibleOutdatedIllustrationPointsSelection(); } private void HandlePossibleOutdatedIllustrationPointsControl() { IEnumerable illustrationPointControlItems = GetIllustrationPointControlItems(); if (illustrationPointsControl.Data.Count() != illustrationPointControlItems.Count()) { illustrationPointsControl.Data = illustrationPointControlItems; } } private void HandlePossibleOutdatedIllustrationPointsSelection() { if (illustrationPointsControl.Selection == null && Selection is SelectedTopLevelSubMechanismIllustrationPoint) { ProvideLocationSelection(); } } private void LocalizeControls() { CalculateForSelectedButton.Text = Resources.CalculatableView_CalculateForSelectedButton_Text; DeselectAllButton.Text = Resources.CalculatableView_DeselectAllButton_Text; SelectAllButton.Text = Resources.CalculatableView_SelectAllButton_Text; ButtonGroupBox.Text = Resources.CalculatableView_ButtonGroupBox_Text; } private void InitializeEventHandlers() { dataGridViewControl.CurrentRowChanged += DataGridViewControlOnCurrentRowChanged; dataGridViewControl.CellValueChanged += DataGridViewControlOnCellValueChanged; illustrationPointsControl.SelectionChanged += IllustrationPointsControlOnSelectionChanged; } private void OnSelectionChanged() { SelectionChanged?.Invoke(this, new EventArgs()); } private void ProvideLocationSelection() { Selection = CreateSelectedItemFromCurrentRow(); OnSelectionChanged(); } #region Event handling private void DataGridViewControlOnCurrentRowChanged(object sender, EventArgs e) { if (suspendAllEvents) { return; } suspendIllustrationPointsControlSelectionChanges = true; illustrationPointsControl.Data = GetIllustrationPointControlItems(); suspendIllustrationPointsControlSelectionChanges = false; ProvideLocationSelection(); } private void DataGridViewControlOnCellValueChanged(object sender, DataGridViewCellEventArgs e) { if (suspendAllEvents || e.ColumnIndex != calculateColumnIndex) { return; } UpdateCalculateForSelectedButton(); } private void IllustrationPointsControlOnSelectionChanged(object sender, EventArgs eventArgs) { if (suspendAllEvents || suspendIllustrationPointsControlSelectionChanges) { return; } var selection = illustrationPointsControl.Selection as IllustrationPointControlItem; Selection = selection != null ? new SelectedTopLevelSubMechanismIllustrationPoint((TopLevelSubMechanismIllustrationPoint) selection.Source, GetIllustrationPointControlItems().Select(ipci => ipci.ClosingSituation).ToArray()) : null; OnSelectionChanged(); } /// /// Gets the illustration point control items based on the data of the illustration points. /// /// The illustration point control items if it has obtained as part of the calculation, null /// otherwise. protected abstract IEnumerable GetIllustrationPointControlItems(); private void SelectAllButton_Click(object sender, EventArgs e) { SetShouldCalculateForAllRowsAndRefresh(true); } private void DeselectAllButton_Click(object sender, EventArgs e) { SetShouldCalculateForAllRowsAndRefresh(false); } private void SetShouldCalculateForAllRowsAndRefresh(bool newShouldCalculateValue) { GetCalculatableRows().ForEachElementDo(row => row.ShouldCalculate = newShouldCalculateValue); dataGridViewControl.RefreshDataGridView(); UpdateCalculateForSelectedButton(); } private void CalculateForSelectedButton_Click(object sender, EventArgs e) { CalculateForSelectedRows(); } #endregion } }