#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();
}
}
}