using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using HeuristicLab.MainForm; using HeuristicLab.MainForm.WindowsForms; using System.Windows.Forms; using HeuristicLab.Common; namespace HeuristicLab.Data.MoveVectorData.Views { [View("Stacking Area View")] [Content(typeof(StackingArea), IsDefaultView = true)] public partial class StackingAreaView : AsynchronousContentView { protected int[] virtualRowIndices; public new IStringConvertibleMatrix Content { get { return (IStringConvertibleMatrix)base.Content; } set { base.Content = value; } } public DataGridView DataGridView { get { return dataGridView; } } public override bool ReadOnly { get { if ((Content != null) && Content.ReadOnly) return true; return base.ReadOnly; } set { base.ReadOnly = value; } } public StackingAreaView() { InitializeComponent(); } 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(); if (Content == null) { dataGridView.Rows.Clear(); dataGridView.Columns.Clear(); virtualRowIndices = new int[0]; } else if (!dataGridView.IsCurrentCellInEditMode) { UpdateData(); } } protected override void SetEnabledStateOfControls() { base.SetEnabledStateOfControls(); dataGridView.Enabled = Content != null; dataGridView.ReadOnly = ReadOnly; } protected virtual void UpdateData() { virtualRowIndices = Enumerable.Range(0, Content.Rows).Reverse().ToArray(); if (Content.Columns == 0 && dataGridView.ColumnCount != Content.Columns && !Content.ReadOnly) Content.Columns = dataGridView.ColumnCount; else { DataGridViewColumn[] columns = new DataGridViewColumn[Content.Columns]; for (int i = 0; i < columns.Length; ++i) { var column = new DataGridViewTextBoxColumn(); column.FillWeight = 1; columns[i] = column; } dataGridView.Columns.Clear(); dataGridView.Columns.AddRange(columns); } //DataGridViews with rows but no columns are not allowed ! if (Content.Rows == 0 && dataGridView.RowCount != Content.Rows && !Content.ReadOnly) Content.Rows = dataGridView.RowCount; else dataGridView.RowCount = Content.Rows; UpdateColumnHeaders(); UpdateRowHeaders(); dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.ColumnHeader); dataGridView.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders); dataGridView.Enabled = true; } public virtual void UpdateColumnHeaders() { HashSet invisibleColumnNames = new HashSet(dataGridView.Columns.OfType() .Where(c => !c.Visible && !string.IsNullOrEmpty(c.HeaderText)).Select(c => c.HeaderText)); for (int i = 0; i < dataGridView.ColumnCount; i++) { if (i < Content.ColumnNames.Count()) dataGridView.Columns[i].HeaderText = Content.ColumnNames.ElementAt(i); else dataGridView.Columns[i].HeaderText = "Stack " + (i + 1 - 1); dataGridView.Columns[i].Visible = !invisibleColumnNames.Contains(dataGridView.Columns[i].HeaderText); } } public virtual void UpdateRowHeaders() { int index = dataGridView.FirstDisplayedScrollingRowIndex; if (index == -1) index = 0; int updatedRows = 0; int count = dataGridView.DisplayedRowCount(true); while (updatedRows < count) { if (virtualRowIndices[index] < Content.RowNames.Count()) dataGridView.Rows[index].HeaderCell.Value = Content.RowNames.ElementAt(virtualRowIndices[index]); else dataGridView.Rows[index].HeaderCell.Value = "Tier " + (count - index - 1); if (dataGridView.Rows[index].Visible) updatedRows++; index++; } } private void Content_RowNamesChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_RowNamesChanged), sender, e); else UpdateRowHeaders(); } private void Content_ColumnNamesChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_ColumnNamesChanged), sender, e); else UpdateColumnHeaders(); } private void Content_ItemChanged(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler>(Content_ItemChanged), sender, e); else dataGridView.InvalidateCell(e.Value2, e.Value); } private void Content_Reset(object sender, EventArgs e) { if (InvokeRequired) Invoke(new EventHandler(Content_Reset), sender, e); else UpdateData(); } #region DataGridView Events protected virtual void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { if (!dataGridView.ReadOnly) { string errorMessage; if (Content != null && !Content.Validate(e.FormattedValue.ToString(), out errorMessage)) { e.Cancel = true; dataGridView.Rows[e.RowIndex].ErrorText = errorMessage; } } } protected virtual void dataGridView_CellParsing(object sender, DataGridViewCellParsingEventArgs e) { if (!dataGridView.ReadOnly) { string value = e.Value.ToString(); int rowIndex = virtualRowIndices[e.RowIndex]; e.ParsingApplied = Content != null && 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; } protected virtual void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) { if (Content != null && e.RowIndex < Content.Rows && e.ColumnIndex < Content.Columns) { int rowIndex = virtualRowIndices[e.RowIndex]; e.Value = Content.GetValue(rowIndex, e.ColumnIndex); } } private void dataGridView_Scroll(object sender, System.Windows.Forms.ScrollEventArgs e) { this.UpdateRowHeaders(); } private void dataGridView_Resize(object sender, EventArgs e) { this.UpdateRowHeaders(); } protected virtual void dataGridView_KeyDown(object sender, KeyEventArgs e) { if (!ReadOnly && e.Control && e.KeyCode == Keys.V) PasteValuesToDataGridView(); else if (e.Control && e.KeyCode == Keys.C) CopyValuesFromDataGridView(); } private void CopyValuesFromDataGridView() { if (dataGridView.SelectedCells.Count == 0) return; StringBuilder s = new StringBuilder(); int minRowIndex = dataGridView.SelectedCells[0].RowIndex; int maxRowIndex = dataGridView.SelectedCells[dataGridView.SelectedCells.Count - 1].RowIndex; int minColIndex = dataGridView.SelectedCells[0].ColumnIndex; int maxColIndex = dataGridView.SelectedCells[dataGridView.SelectedCells.Count - 1].ColumnIndex; if (minRowIndex > maxRowIndex) { int temp = minRowIndex; minRowIndex = maxRowIndex; maxRowIndex = temp; } if (minColIndex > maxColIndex) { int temp = minColIndex; minColIndex = maxColIndex; maxColIndex = temp; } bool addRowNames = dataGridView.AreAllCellsSelected(false) && Content.RowNames.Count() > 0; bool addColumnNames = dataGridView.AreAllCellsSelected(false) && Content.ColumnNames.Count() > 0; //add colum names if (addColumnNames) { if (addRowNames) s.Append('\t'); DataGridViewColumn column = dataGridView.Columns.GetFirstColumn(DataGridViewElementStates.Visible); while (column != null) { s.Append(column.HeaderText); s.Append('\t'); column = dataGridView.Columns.GetNextColumn(column, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } s.Remove(s.Length - 1, 1); //remove last tab s.Append(Environment.NewLine); } for (int i = minRowIndex; i <= maxRowIndex; i++) { if (!dataGridView.Rows[i].Visible) continue; int rowIndex = this.virtualRowIndices[i]; if (addRowNames) { s.Append(Content.RowNames.ElementAt(rowIndex)); s.Append('\t'); } DataGridViewColumn column = dataGridView.Columns.GetFirstColumn(DataGridViewElementStates.Visible); while (column != null) { DataGridViewCell cell = dataGridView[column.Index, i]; if (cell.Selected) { s.Append(Content.GetValue(rowIndex, column.Index)); s.Append('\t'); } column = dataGridView.Columns.GetNextColumn(column, DataGridViewElementStates.Visible, DataGridViewElementStates.None); } s.Remove(s.Length - 1, 1); //remove last tab s.Append(Environment.NewLine); } Clipboard.SetText(s.ToString()); } protected virtual void PasteValuesToDataGridView() { string[,] values = SplitClipboardString(Clipboard.GetText()); int rowIndex = 0; int columnIndex = 0; if (dataGridView.CurrentCell != null) { rowIndex = virtualRowIndices[dataGridView.CurrentCell.RowIndex]; columnIndex = dataGridView.CurrentCell.ColumnIndex; } if (Content.Rows < values.GetLength(1) + rowIndex) Content.Rows = values.GetLength(1) + rowIndex; if (Content.Columns < values.GetLength(0) + columnIndex) Content.Columns = values.GetLength(0) + columnIndex; for (int row = 0; row < values.GetLength(1); row++) { for (int col = 0; col < values.GetLength(0); col++) { Content.SetValue(values[col, values.GetLength(1) - 1 - row], row + rowIndex, col + columnIndex); } } } protected string[,] SplitClipboardString(string clipboardText) { if (clipboardText.EndsWith(Environment.NewLine)) clipboardText = clipboardText.Remove(clipboardText.Length - Environment.NewLine.Length); //remove last newline constant string[,] values = null; string[] lines = clipboardText.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); string[] cells; for (int i = 0; i < lines.Length; i++) { cells = lines[i].Split('\t'); if (values == null) values = new string[cells.Length, lines.Length]; for (int j = 0; j < cells.Length; j++) values[j, i] = string.IsNullOrEmpty(cells[j]) ? string.Empty : cells[j]; } return values; } protected virtual void dataGridView_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) { if (Content == null) return; if (e.Button == MouseButtons.Right && Content.ColumnNames.Count() != 0) contextMenu.Show(MousePosition); } } #endregion }