#region License Information /* HeuristicLab * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab 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. * * HeuristicLab 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 HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using HeuristicLab.Data; using HeuristicLab.DataPreprocessing.Filter; using HeuristicLab.MainForm; namespace HeuristicLab.DataPreprocessing.Views { [View("Data Grid Content View")] [Content(typeof(IDataGridContent), true)] public partial class DataGridContentView : CopyOfStringConvertibleMatrixView { private bool notOwnEvent = true; private SearchAndReplaceDialog findAndReplaceDialog; private IFindPreprocessingItemsIterator searchIterator; private string currentSearchText; private Tuple currentCell; public new IDataGridContent Content { get { return (IDataGridContent)base.Content; } set { base.Content = value; } } private IList _highlightedRowIndices; public IList HighlightedRowIndices { get { return _highlightedRowIndices; } set { _highlightedRowIndices = value; Refresh(); } } private IDictionary> _highlightedCells; public IDictionary> HightlightedCells { get { return _highlightedCells; } set { _highlightedCells = value; Refresh(); } } private IDictionary> _highlightedCellsBackground; public IDictionary> HightlightedCellsBackground { get { return _highlightedCellsBackground; } set { _highlightedCellsBackground = value; Refresh(); } } public DataGridContentView() { InitializeComponent(); dataGridView.CellMouseClick += dataGridView_CellMouseClick; dataGridView.CellPainting += new System.Windows.Forms.DataGridViewCellPaintingEventHandler(dataGridView_CellPainting); dataGridView.KeyDown += dataGridView_KeyDown; contextMenuCell.Items.Add(ShowHideColumns); _highlightedCells = new Dictionary>(); _highlightedRowIndices = new List(); _highlightedCellsBackground = new Dictionary>(); currentCell = null; } protected override void OnContentChanged() { base.OnContentChanged(); if (Content == null && findAndReplaceDialog != null) { findAndReplaceDialog.Close(); } } protected override void RegisterContentEvents() { base.RegisterContentEvents(); Content.Changed += Content_Changed; } protected override void DeregisterContentEvents() { base.DeregisterContentEvents(); Content.Changed -= Content_Changed; } void Content_Changed(object sender, DataPreprocessingChangedEventArgs e) { if (notOwnEvent) { switch (e.Type) { case DataPreprocessingChangedEventType.AddColumn: case DataPreprocessingChangedEventType.AddRow: case DataPreprocessingChangedEventType.DeleteColumn: case DataPreprocessingChangedEventType.DeleteRow: case DataPreprocessingChangedEventType.Any: OnContentChanged(); break; case DataPreprocessingChangedEventType.ChangeColumn: case DataPreprocessingChangedEventType.ChangeItem: dataGridView.Refresh(); break; } } } protected override void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { if (!dataGridView.ReadOnly) { string errorMessage; if (Content != null && !Content.DataGridLogic.Validate(e.FormattedValue.ToString(), out errorMessage, e.ColumnIndex)) { e.Cancel = true; dataGridView.Rows[e.RowIndex].ErrorText = errorMessage; } } } protected override void dataGridView_CellParsing(object sender, DataGridViewCellParsingEventArgs e) { triggersOwnEvent(() => base.dataGridView_CellParsing(sender, e)); } protected override void PasteValuesToDataGridView() { triggersOwnEvent(() => base.PasteValuesToDataGridView()); } protected override void SetEnabledStateOfControls() { base.SetEnabledStateOfControls(); rowsTextBox.ReadOnly = true; columnsTextBox.ReadOnly = true; } private void btnApplySort_Click(object sender, System.EventArgs e) { triggersOwnEvent(() => { Content.PreprocessingDataManipulation.ReOrderToIndices(virtualRowIndices); OnContentChanged(); }); } private void triggersOwnEvent(Action action) { notOwnEvent = false; action(); notOwnEvent = true; } #region FindAndReplaceDialog private void CreateFindAndReplaceDialog() { findAndReplaceDialog = new SearchAndReplaceDialog(); findAndReplaceDialog.Show(this); HightlightedCellsBackground = GetSelectedCells(); dataGridView.ClearSelection(); findAndReplaceDialog.FindAllEvent += findAndReplaceDialog_FindAllEvent; findAndReplaceDialog.FindNextEvent += findAndReplaceDialog_FindNextEvent; findAndReplaceDialog.ReplaceAllEvent += findAndReplaceDialog_ReplaceAllEvent; findAndReplaceDialog.ReplaceNextEvent += findAndReplaceDialog_ReplaceEvent; findAndReplaceDialog.FormClosing += findAndReplaceDialog_FormClosing; } void findAndReplaceDialog_FormClosing(object sender, FormClosingEventArgs e) { ResetHighlightedCells(); ResetHighlightedCellsBackground(); } void findAndReplaceDialog_ReplaceEvent(object sender, EventArgs e) { if (searchIterator != null && searchIterator.GetCurrent() != null) { Replace(TransformToDictionary(currentCell)); } } void findAndReplaceDialog_ReplaceAllEvent(object sender, EventArgs e) { Replace(FindAll(findAndReplaceDialog.GetSearchText())); } void findAndReplaceDialog_FindNextEvent(object sender, EventArgs e) { if (searchIterator == null || currentSearchText != findAndReplaceDialog.GetSearchText()) { searchIterator = new FindPreprocessingItemsIterator(FindAll(findAndReplaceDialog.GetSearchText())); currentSearchText = findAndReplaceDialog.GetSearchText(); } bool moreOccurences = false; do { currentCell = searchIterator.GetCurrent(); moreOccurences = searchIterator.MoveNext(); } while (moreOccurences && (currentCell == null || !Content.GetValue(currentCell.Item2, currentCell.Item1).Equals(currentSearchText))); if (currentCell != null) { HightlightedCells = TransformToDictionary(currentCell); dataGridView.FirstDisplayedCell = dataGridView[currentCell.Item1, currentCell.Item2]; } else { ResetHighlightedCells(); } if (!moreOccurences) { searchIterator.Reset(); } } void findAndReplaceDialog_FindAllEvent(object sender, EventArgs e) { HightlightedCells = FindAll(findAndReplaceDialog.GetSearchText()); } private IDictionary> FindAll(string match) { bool searchInSelection = HightlightedCellsBackground.Values.Sum(list => list.Count) > 1; var comparisonFilter = new ComparisonFilter(Content.FilterLogic.PreprocessingData, Core.ConstraintOperation.Equal, new StringValue(match), true); var filters = new List() { comparisonFilter }; var foundCells = new Dictionary>(); for (int i = 0; i < Content.FilterLogic.PreprocessingData.Columns; i++) { comparisonFilter.ConstraintColumn = i; bool[] filteredRows = Content.FilterLogic.Preview(filters, true); foundCells[i] = filteredRows.Select((value, index) => new { Index = index, Value = value }) .Where(pair => pair.Value) .Select(pair => pair.Index) .ToList(); IList selectedList; if (searchInSelection && HightlightedCellsBackground.TryGetValue(i, out selectedList)) { foundCells[i] = foundCells[i].Intersect(selectedList).ToList(); } else if (searchInSelection) { foundCells[i].Clear(); } } return foundCells; } private void Replace(IDictionary> cells) { if (findAndReplaceDialog != null) { switch (findAndReplaceDialog.GetReplaceAction()) { case ReplaceAction.Value: Content.PreprocessingDataManipulation.ReplaceIndicesByValue(cells, findAndReplaceDialog.GetReplaceText()); break; case ReplaceAction.Average: Content.PreprocessingDataManipulation.ReplaceIndicesByAverageValue(cells); break; case ReplaceAction.Median: Content.PreprocessingDataManipulation.ReplaceIndicesByMedianValue(cells); break; case ReplaceAction.Random: Content.PreprocessingDataManipulation.ReplaceIndicesByRandomValue(cells); break; case ReplaceAction.MostCommon: Content.PreprocessingDataManipulation.ReplaceIndicesByMostCommonValue(cells); break; case ReplaceAction.Interpolation: Content.PreprocessingDataManipulation.ReplaceIndicesByLinearInterpolationOfNeighbours(cells); break; } } } private IDictionary> TransformToDictionary(Tuple tuple) { var highlightCells = new Dictionary>(); highlightCells.Add(tuple.Item1, new List() { tuple.Item2 }); return highlightCells; } private void ResetHighlightedCells() { HightlightedCells = new Dictionary>(); } private void ResetHighlightedCellsBackground() { HightlightedCellsBackground = new Dictionary>(); } #endregion FindAndReplaceDialog private void dataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) { if (Content == null) return; if (e.Button == System.Windows.Forms.MouseButtons.Right) { if (e.ColumnIndex == -1 || e.RowIndex == -1) { replaceValueOverColumnToolStripMenuItem.Visible = false; contextMenuCell.Show(MousePosition); } else { if (!dataGridView.SelectedCells.Contains(dataGridView[e.ColumnIndex, e.RowIndex])) { dataGridView.ClearSelection(); dataGridView[e.ColumnIndex, e.RowIndex].Selected = true; } interpolationToolStripMenuItem_Column.Enabled = !(e.RowIndex == 0 || e.RowIndex == Content.Rows); var columnIndices = new HashSet(); for (int i = 0; i < dataGridView.SelectedCells.Count; i++) { columnIndices.Add(dataGridView.SelectedCells[i].ColumnIndex); } averageToolStripMenuItem_Column.Enabled = medianToolStripMenuItem_Column.Enabled = randomToolStripMenuItem_Column.Enabled = !Content.DataGridLogic.AreAllStringColumns(columnIndices); interpolationToolStripMenuItem_Column.Enabled = interpolationToolStripMenuItem_Column.Enabled && !Content.DataGridLogic.AreAllStringColumns(columnIndices); replaceValueOverColumnToolStripMenuItem.Visible = true; contextMenuCell.Show(MousePosition); } } } protected void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (Content == null) return; if (e.RowIndex < 0) return; if (e.ColumnIndex < 0) return; if (e.State.HasFlag(DataGridViewElementStates.Selected)) return; if (!e.PaintParts.HasFlag(DataGridViewPaintParts.Background)) return; if (HighlightedRowIndices == null && HightlightedCells == null) return; int rowIndex = virtualRowIndices[e.RowIndex]; Color backColor = e.CellStyle.BackColor; if (HightlightedCellsBackground.ContainsKey(e.ColumnIndex) && HightlightedCellsBackground[e.ColumnIndex].Contains(e.RowIndex)) { backColor = Color.LightGray; } if (HighlightedRowIndices.Contains(rowIndex) || HightlightedCells.ContainsKey(e.ColumnIndex) && HightlightedCells[e.ColumnIndex].Contains(e.RowIndex)) { backColor = Color.LightGreen; } using (Brush backColorBrush = new SolidBrush(backColor)) { Rectangle bounds = new Rectangle(e.CellBounds.X, e.CellBounds.Y, e.CellBounds.Width, e.CellBounds.Height); e.Graphics.FillRectangle(backColorBrush, bounds); } using (Brush gridBrush = new SolidBrush(Color.LightGray)) { Pen gridLinePen = new Pen(gridBrush); e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1); e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom); } e.PaintContent(e.CellBounds); e.Handled = true; } void dataGridView_KeyDown(object sender, KeyEventArgs e) { var selectedRows = dataGridView.SelectedRows; if (e.KeyCode == Keys.Delete && selectedRows.Count > 0) { List rows = new List(); for (int i = 0; i < selectedRows.Count; ++i) { rows.Add(selectedRows[i].Index); } triggersOwnEvent(() => { Content.DataGridLogic.DeleteRow(rows); OnContentChanged(); }); } else if (e.Control && e.KeyCode == Keys.F) { CreateFindAndReplaceDialog(); findAndReplaceDialog.ActivateSearch(); } else if (e.Control && e.KeyCode == Keys.R) { CreateFindAndReplaceDialog(); findAndReplaceDialog.ActivateReplace(); } } protected override int[] Sort(IEnumerable> sortedColumns) { btnApplySort.Enabled = sortedColumns.Any(); return base.Sort(sortedColumns); } protected override void ClearSorting() { btnApplySort.Enabled = false; base.ClearSorting(); } private IDictionary> GetSelectedCells() { IDictionary> selectedCells = new Dictionary>(); for (int i = 0; i < dataGridView.SelectedCells.Count; i++) { var columnIndex = dataGridView.SelectedCells[i].ColumnIndex; if (!selectedCells.ContainsKey(columnIndex)) { selectedCells.Add(columnIndex, new List()); } selectedCells[columnIndex].Add(dataGridView.SelectedCells[i].RowIndex); } return selectedCells; } private void ReplaceWithAverage_Column_Click(object sender, EventArgs e) { Content.PreprocessingDataManipulation.ReplaceIndicesByAverageValue(GetSelectedCells()); } private void ReplaceWithMedian_Column_Click(object sender, EventArgs e) { Content.PreprocessingDataManipulation.ReplaceIndicesByMedianValue(GetSelectedCells()); } private void ReplaceWithRandom_Column_Click(object sender, EventArgs e) { Content.PreprocessingDataManipulation.ReplaceIndicesByRandomValue(GetSelectedCells()); } private void ReplaceWithMostCommon_Column_Click(object sender, EventArgs e) { Content.PreprocessingDataManipulation.ReplaceIndicesByMostCommonValue(GetSelectedCells()); } private void ReplaceWithInterpolation_Column_Click(object sender, EventArgs e) { Content.PreprocessingDataManipulation.ReplaceIndicesByLinearInterpolationOfNeighbours(GetSelectedCells()); } private void ReplaceWithAverage_Selection_Click(object sender, EventArgs e) { } private void ReplaceWithMedian_Selection_Click(object sender, EventArgs e) { } private void ReplaceWithRandom_Selection_Click(object sender, EventArgs e) { } private void ReplaceWithMostCommon_Selection_Click(object sender, EventArgs e) { } private void ReplaceWithInterpolation_Selection_Click(object sender, EventArgs e) { } private void ReplaceWithSmoothing_Selection_Click(object sender, EventArgs e) { } private void btnSearch_Click(object sender, EventArgs e) { CreateFindAndReplaceDialog(); findAndReplaceDialog.ActivateSearch(); } private void btnReplace_Click(object sender, EventArgs e) { CreateFindAndReplaceDialog(); findAndReplaceDialog.ActivateReplace(); } } }