#region License Information /* HeuristicLab * Copyright (C) 2002-2010 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.ComponentModel; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using HeuristicLab.Common; using HeuristicLab.MainForm; using HeuristicLab.MainForm.WindowsForms; namespace HeuristicLab.Data.Views { [View("StringConvertibleMatrix View")] [Content(typeof(IStringConvertibleMatrix), true)] public partial class StringConvertibleMatrixView : AsynchronousContentView { public new IStringConvertibleMatrix Content { get { return (IStringConvertibleMatrix)base.Content; } set { base.Content = value; } } private int[] virtualRowIndizes; private List> sortedColumnIndizes; RowComparer rowComparer; public StringConvertibleMatrixView() { InitializeComponent(); Caption = "StringConvertibleMatrix View"; errorProvider.SetIconAlignment(rowsTextBox, ErrorIconAlignment.MiddleLeft); errorProvider.SetIconPadding(rowsTextBox, 2); errorProvider.SetIconAlignment(columnsTextBox, ErrorIconAlignment.MiddleLeft); errorProvider.SetIconPadding(columnsTextBox, 2); sortedColumnIndizes = new List>(); rowComparer = new RowComparer(); } public StringConvertibleMatrixView(IStringConvertibleMatrix content) : this() { Content = content; } protected override void DeregisterContentEvents() { Content.ItemChanged -= new EventHandler>(Content_ItemChanged); Content.Reset -= new EventHandler(Content_Reset); Content.ColumnNamesChanged -= new EventHandler(Content_ColumnNamesChanged); Content.RowNamesChanged -= new EventHandler(Content_RowNamesChanged); base.DeregisterContentEvents(); } protected override void RegisterContentEvents() { base.RegisterContentEvents(); Content.ItemChanged += new EventHandler>(Content_ItemChanged); Content.Reset += new EventHandler(Content_Reset); Content.ColumnNamesChanged += new EventHandler(Content_ColumnNamesChanged); Content.RowNamesChanged += new EventHandler(Content_RowNamesChanged); } protected override void OnContentChanged() { base.OnContentChanged(); sortedColumnIndizes.Clear(); if (Content == null) { Caption = "StringConvertibleMatrix View"; rowsTextBox.Text = ""; rowsTextBox.Enabled = false; columnsTextBox.Text = ""; columnsTextBox.Enabled = false; dataGridView.Rows.Clear(); dataGridView.Columns.Clear(); dataGridView.Enabled = false; virtualRowIndizes = new int[0]; } else { Caption = "StringConvertibleMatrix (" + Content.GetType().Name + ")"; UpdateData(); } } private void UpdateData() { rowsTextBox.Text = Content.Rows.ToString(); rowsTextBox.Enabled = true; columnsTextBox.Text = Content.Columns.ToString(); columnsTextBox.Enabled = true; virtualRowIndizes = Enumerable.Range(0, Content.Rows).ToArray(); dataGridView.EndEdit(); dataGridView.RowCount = 0; dataGridView.ColumnCount = 0; if ((Content.Rows > 0) && (Content.Columns > 0)) { dataGridView.RowCount = Content.Rows; dataGridView.ColumnCount = Content.Columns; UpdateRowHeaders(); UpdateColumnHeaders(); } dataGridView.ReadOnly = Content.ReadOnlyView; dataGridView.Enabled = true; } private void UpdateColumnHeaders() { for (int i = 0; i < Content.Columns; i++) { if (Content.ColumnNames.Count() != 0) dataGridView.Columns[i].HeaderText = Content.ColumnNames.ElementAt(i); else dataGridView.Columns[i].HeaderText = "Column " + i; } dataGridView.Invalidate(); } private void UpdateRowHeaders() { for (int i = dataGridView.FirstDisplayedScrollingRowIndex; i < dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(true); i++) { if (Content.RowNames.Count() != 0) dataGridView.Rows[i].HeaderCell.Value = Content.RowNames.ElementAt(i); else dataGridView.Rows[i].HeaderCell.Value = i.ToString(); } dataGridView.Invalidate(); } private void Content_RowNamesChanged(object sender, EventArgs e) { UpdateColumnHeaders(); } private void Content_ColumnNamesChanged(object sender, EventArgs e) { UpdateRowHeaders(); } private void Content_ItemChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler>(Content_ItemChanged), sender, e); else { dataGridView.InvalidateCell(e.Value, e.Value2); } } private void Content_Reset(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_Reset), sender, e); else UpdateData(); } #region TextBox Events private void rowsTextBox_Validating(object sender, CancelEventArgs e) { int i = 0; if (!int.TryParse(rowsTextBox.Text, out i) || (i < 0)) { e.Cancel = true; errorProvider.SetError(rowsTextBox, "Invalid Number of Rows (Valid Values: Positive Integers Larger or Equal to 0)"); rowsTextBox.SelectAll(); } } private void rowsTextBox_Validated(object sender, EventArgs e) { Content.Rows = int.Parse(rowsTextBox.Text); errorProvider.SetError(rowsTextBox, string.Empty); } private void rowsTextBox_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return) rowsLabel.Focus(); // set focus on label to validate data if (e.KeyCode == Keys.Escape) { rowsTextBox.Text = Content.Rows.ToString(); rowsLabel.Focus(); // set focus on label to validate data } } private void columnsTextBox_Validating(object sender, CancelEventArgs e) { int i = 0; if (!int.TryParse(columnsTextBox.Text, out i) || (i < 0)) { e.Cancel = true; errorProvider.SetError(columnsTextBox, "Invalid Number of Columns (Valid Values: Positive Integers Larger or Equal to 0)"); columnsTextBox.SelectAll(); } } private void columnsTextBox_Validated(object sender, EventArgs e) { Content.Columns = int.Parse(columnsTextBox.Text); errorProvider.SetError(columnsTextBox, string.Empty); } private void columnsTextBox_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return) columnsLabel.Focus(); // set focus on label to validate data if (e.KeyCode == Keys.Escape) { columnsTextBox.Text = Content.Columns.ToString(); columnsLabel.Focus(); // set focus on label to validate data } } #endregion #region DataGridView Events private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { string errorMessage; if (!Content.Validate(e.FormattedValue.ToString(), out errorMessage)) { e.Cancel = true; dataGridView.Rows[e.RowIndex].ErrorText = errorMessage; } } private void dataGridView_CellParsing(object sender, DataGridViewCellParsingEventArgs e) { string value = e.Value.ToString(); int rowIndex = virtualRowIndizes[e.RowIndex]; e.ParsingApplied = Content.SetValue(value, rowIndex, e.ColumnIndex); if (e.ParsingApplied) e.Value = Content.GetValue(rowIndex, e.ColumnIndex); } private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) { dataGridView.Rows[e.RowIndex].ErrorText = string.Empty; } private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) { int rowIndex = virtualRowIndizes[e.RowIndex]; e.Value = Content.GetValue(rowIndex, e.ColumnIndex); } private void dataGridView_Scroll(object sender, ScrollEventArgs e) { UpdateRowHeaders(); } private void dataGridView_Resize(object sender, EventArgs e) { UpdateRowHeaders(); } private void dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { if (Content != null) { if (e.Button == MouseButtons.Left && Content.SortableView) { bool addToSortedIndizes = (Control.ModifierKeys & Keys.Control) == Keys.Control; SortOrder newSortOrder = SortOrder.Ascending; if (sortedColumnIndizes.Any(x => x.Key == e.ColumnIndex)) { SortOrder oldSortOrder = sortedColumnIndizes.Where(x => x.Key == e.ColumnIndex).First().Value; int enumLength = Enum.GetValues(typeof(SortOrder)).Length; newSortOrder = oldSortOrder = (SortOrder)Enum.Parse(typeof(SortOrder), ((((int)oldSortOrder) + 1) % enumLength).ToString()); } if (!addToSortedIndizes) sortedColumnIndizes.Clear(); if (sortedColumnIndizes.Any(x => x.Key == e.ColumnIndex)) { int sortedIndex = sortedColumnIndizes.FindIndex(x => x.Key == e.ColumnIndex); if (newSortOrder != SortOrder.None) sortedColumnIndizes[sortedIndex] = new KeyValuePair(e.ColumnIndex, newSortOrder); else sortedColumnIndizes.RemoveAt(sortedIndex); } else if (newSortOrder != SortOrder.None) sortedColumnIndizes.Add(new KeyValuePair(e.ColumnIndex, newSortOrder)); Sort(); } else if (e.Button == MouseButtons.Right) { if (Content.ColumnNames.Count() != 0) contextMenu.Show(MousePosition); } } } private void Sort() { int[] newSortedIndex = Enumerable.Range(0, Content.Rows - 1).ToArray(); if (sortedColumnIndizes.Count != 0) { rowComparer.sortedIndizes = sortedColumnIndizes; rowComparer.matrix = Content; Array.Sort(newSortedIndex, rowComparer); } virtualRowIndizes = newSortedIndex; dataGridView.Invalidate(); foreach (DataGridViewColumn col in this.dataGridView.Columns) col.HeaderCell.SortGlyphDirection = SortOrder.None; foreach (KeyValuePair p in sortedColumnIndizes) this.dataGridView.Columns[p.Key].HeaderCell.SortGlyphDirection = p.Value; } #endregion private class RowComparer : IComparer { public List> sortedIndizes; public IStringConvertibleMatrix matrix; public RowComparer() { } public int Compare(int x, int y) { int result = 0; double double1, double2; DateTime dateTime1, dateTime2; string string1, string2; foreach (KeyValuePair pair in sortedIndizes) { string1 = matrix.GetValue(x, pair.Key); string2 = matrix.GetValue(y, pair.Key); if (double.TryParse(string1, out double1) && double.TryParse(string2, out double2)) result = double1.CompareTo(double2); else if (DateTime.TryParse(string1, out dateTime1) && DateTime.TryParse(string2, out dateTime2)) result = dateTime1.CompareTo(dateTime2); else { if (string1 != null) result = string1.CompareTo(string2); else if (string2 != null) result = string2.CompareTo(string1) * -1; } if (pair.Value == SortOrder.Descending) result *= -1; if (result != 0) return result; } return result; } } private void ShowHideColumns_Click(object sender, EventArgs e) { new ColumnsVisibilityDialog(this.dataGridView.Columns.Cast()).ShowDialog(); } } }