Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Data.Views/3.3/StringConvertibleMatrixView.cs @ 3328

Last change on this file since 3328 was 3328, checked in by mkommend, 14 years ago

added new functionality and bug fixed to StringConvertibleMatrixView (ticket #968)

File size: 13.6 KB
RevLine 
[2669]1#region License Information
2/* HeuristicLab
[2790]3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[2669]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.ComponentModel;
[3314]24using System.Collections.Generic;
[2669]25using System.Drawing;
[3312]26using System.Linq;
[2669]27using System.Windows.Forms;
28using HeuristicLab.Common;
29using HeuristicLab.MainForm;
[2713]30using HeuristicLab.MainForm.WindowsForms;
[2669]31
32namespace HeuristicLab.Data.Views {
[3048]33  [View("StringConvertibleMatrix View")]
34  [Content(typeof(IStringConvertibleMatrix), true)]
[3228]35  public partial class StringConvertibleMatrixView : AsynchronousContentView {
[3048]36    public new IStringConvertibleMatrix Content {
37      get { return (IStringConvertibleMatrix)base.Content; }
[2713]38      set { base.Content = value; }
[2669]39    }
40
[3314]41    private int[] virtualRowIndizes;
42    private List<KeyValuePair<int, SortOrder>> sortedColumnIndizes;
43    RowComparer rowComparer;
44
[3048]45    public StringConvertibleMatrixView() {
[2669]46      InitializeComponent();
[3048]47      Caption = "StringConvertibleMatrix View";
[2677]48      errorProvider.SetIconAlignment(rowsTextBox, ErrorIconAlignment.MiddleLeft);
49      errorProvider.SetIconPadding(rowsTextBox, 2);
50      errorProvider.SetIconAlignment(columnsTextBox, ErrorIconAlignment.MiddleLeft);
51      errorProvider.SetIconPadding(columnsTextBox, 2);
[3314]52      sortedColumnIndizes = new List<KeyValuePair<int, SortOrder>>();
53      rowComparer = new RowComparer();
[2669]54    }
[3048]55    public StringConvertibleMatrixView(IStringConvertibleMatrix content)
[2669]56      : this() {
[2727]57      Content = content;
[2669]58    }
59
[2713]60    protected override void DeregisterContentEvents() {
61      Content.ItemChanged -= new EventHandler<EventArgs<int, int>>(Content_ItemChanged);
62      Content.Reset -= new EventHandler(Content_Reset);
[3320]63      Content.ColumnNamesChanged -= new EventHandler(Content_ColumnNamesChanged);
64      Content.RowNamesChanged -= new EventHandler(Content_RowNamesChanged);
[3328]65      Content.ReadOnlyViewChanged -= new EventHandler(Content_ReadOnlyViewChanged);
[2713]66      base.DeregisterContentEvents();
[2669]67    }
68
[2713]69    protected override void RegisterContentEvents() {
70      base.RegisterContentEvents();
71      Content.ItemChanged += new EventHandler<EventArgs<int, int>>(Content_ItemChanged);
72      Content.Reset += new EventHandler(Content_Reset);
[3320]73      Content.ColumnNamesChanged += new EventHandler(Content_ColumnNamesChanged);
74      Content.RowNamesChanged += new EventHandler(Content_RowNamesChanged);
[3328]75      Content.ReadOnlyViewChanged += new EventHandler(Content_ReadOnlyViewChanged);
[2669]76    }
77
[3320]78
[2713]79    protected override void OnContentChanged() {
80      base.OnContentChanged();
81      if (Content == null) {
[3048]82        Caption = "StringConvertibleMatrix View";
[2677]83        rowsTextBox.Text = "";
84        rowsTextBox.Enabled = false;
85        columnsTextBox.Text = "";
86        columnsTextBox.Enabled = false;
[2669]87        dataGridView.Rows.Clear();
[2677]88        dataGridView.Columns.Clear();
[2669]89        dataGridView.Enabled = false;
[3324]90        virtualRowIndizes = new int[0];
[2669]91      } else {
[3048]92        Caption = "StringConvertibleMatrix (" + Content.GetType().Name + ")";
[3328]93        UpdateReadOnlyControls();
[2713]94        UpdateData();
[2669]95      }
96    }
97
[2713]98    private void UpdateData() {
[3328]99      sortedColumnIndizes.Clear();
100      Sort();
[2713]101      rowsTextBox.Text = Content.Rows.ToString();
[2973]102      rowsTextBox.Enabled = true;
[2713]103      columnsTextBox.Text = Content.Columns.ToString();
[2973]104      columnsTextBox.Enabled = true;
[3324]105      virtualRowIndizes = Enumerable.Range(0, Content.Rows).ToArray();
[3328]106      dataGridView.RowCount = Content.Rows;
107      dataGridView.ColumnCount = Content.Columns;
108      UpdateRowHeaders();
109      UpdateColumnHeaders();
[2669]110      dataGridView.Enabled = true;
111    }
112
[3312]113    private void UpdateColumnHeaders() {
114      for (int i = 0; i < Content.Columns; i++) {
115        if (Content.ColumnNames.Count() != 0)
116          dataGridView.Columns[i].HeaderText = Content.ColumnNames.ElementAt(i);
117        else
118          dataGridView.Columns[i].HeaderText = "Column " + i;
119      }
120      dataGridView.Invalidate();
121    }
122
123    private void UpdateRowHeaders() {
124      for (int i = dataGridView.FirstDisplayedScrollingRowIndex; i < dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(true); i++) {
125        if (Content.RowNames.Count() != 0)
126          dataGridView.Rows[i].HeaderCell.Value = Content.RowNames.ElementAt(i);
[3314]127        else
[3312]128          dataGridView.Rows[i].HeaderCell.Value = i.ToString();
129      }
130      dataGridView.Invalidate();
131    }
132
[3328]133    private void UpdateReadOnlyControls() {
134      dataGridView.ReadOnly = Content.ReadOnlyView;
135      rowsTextBox.ReadOnly = Content.ReadOnlyView;
136      columnsTextBox.ReadOnly = Content.ReadOnlyView;
137    }
138
[3320]139    private void Content_RowNamesChanged(object sender, EventArgs e) {
[3328]140      if (InvokeRequired)
141        Invoke(new EventHandler(Content_RowNamesChanged), sender, e);
142      else
143        UpdateRowHeaders();
[3320]144    }
145    private void Content_ColumnNamesChanged(object sender, EventArgs e) {
[3328]146      if (InvokeRequired)
147        Invoke(new EventHandler(Content_ColumnNamesChanged), sender, e);
148      else
149        UpdateColumnHeaders();
[3320]150    }
[2713]151    private void Content_ItemChanged(object sender, EventArgs<int, int> e) {
[2669]152      if (InvokeRequired)
[2713]153        Invoke(new EventHandler<EventArgs<int, int>>(Content_ItemChanged), sender, e);
[3328]154      else
[3314]155        dataGridView.InvalidateCell(e.Value, e.Value2);
[2669]156    }
[2713]157    private void Content_Reset(object sender, EventArgs e) {
[2669]158      if (InvokeRequired)
[2713]159        Invoke(new EventHandler(Content_Reset), sender, e);
[2669]160      else
[2713]161        UpdateData();
[2669]162    }
163
[3328]164    private void Content_ReadOnlyViewChanged(object sender, EventArgs e) {
165      if (InvokeRequired)
166        Invoke(new EventHandler(Content_ReadOnlyViewChanged), sender, e);
167      else
168        UpdateReadOnlyControls();
169    }
170
[2677]171    #region TextBox Events
172    private void rowsTextBox_Validating(object sender, CancelEventArgs e) {
[2669]173      int i = 0;
[2677]174      if (!int.TryParse(rowsTextBox.Text, out i) || (i < 0)) {
[2676]175        e.Cancel = true;
[2694]176        errorProvider.SetError(rowsTextBox, "Invalid Number of Rows (Valid Values: Positive Integers Larger or Equal to 0)");
[2677]177        rowsTextBox.SelectAll();
[2669]178      }
179    }
[2677]180    private void rowsTextBox_Validated(object sender, EventArgs e) {
[3328]181      int textBoxValue = int.Parse(rowsTextBox.Text);
182      if (textBoxValue != Content.Rows)
183        Content.Rows = textBoxValue;
[2677]184      errorProvider.SetError(rowsTextBox, string.Empty);
[2669]185    }
[2677]186    private void rowsTextBox_KeyDown(object sender, KeyEventArgs e) {
[2669]187      if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
[2677]188        rowsLabel.Focus();  // set focus on label to validate data
[2676]189      if (e.KeyCode == Keys.Escape) {
[2973]190        rowsTextBox.Text = Content.Rows.ToString();
[2677]191        rowsLabel.Focus();  // set focus on label to validate data
[2676]192      }
[2669]193    }
[2677]194    private void columnsTextBox_Validating(object sender, CancelEventArgs e) {
195      int i = 0;
196      if (!int.TryParse(columnsTextBox.Text, out i) || (i < 0)) {
197        e.Cancel = true;
[2694]198        errorProvider.SetError(columnsTextBox, "Invalid Number of Columns (Valid Values: Positive Integers Larger or Equal to 0)");
[2677]199        columnsTextBox.SelectAll();
200      }
201    }
202    private void columnsTextBox_Validated(object sender, EventArgs e) {
[3328]203      int textBoxValue = int.Parse(columnsTextBox.Text);
204      if (textBoxValue != Content.Columns)
205        Content.Columns = textBoxValue;
[2677]206      errorProvider.SetError(columnsTextBox, string.Empty);
207    }
208    private void columnsTextBox_KeyDown(object sender, KeyEventArgs e) {
209      if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
210        columnsLabel.Focus();  // set focus on label to validate data
211      if (e.KeyCode == Keys.Escape) {
[2713]212        columnsTextBox.Text = Content.Columns.ToString();
[2677]213        columnsLabel.Focus();  // set focus on label to validate data
214      }
215    }
216    #endregion
217
218    #region DataGridView Events
[2669]219    private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
[3328]220      if (!dataGridView.ReadOnly) {
221        string errorMessage;
222        if (!Content.Validate(e.FormattedValue.ToString(), out errorMessage)) {
223          e.Cancel = true;
224          dataGridView.Rows[e.RowIndex].ErrorText = errorMessage;
225        }
[2676]226      }
[2669]227    }
[2676]228    private void dataGridView_CellParsing(object sender, DataGridViewCellParsingEventArgs e) {
[3328]229      if (!dataGridView.ReadOnly) {
230        string value = e.Value.ToString();
231        int rowIndex = virtualRowIndizes[e.RowIndex];
232        e.ParsingApplied = Content.SetValue(value, rowIndex, e.ColumnIndex);
233        if (e.ParsingApplied) e.Value = Content.GetValue(rowIndex, e.ColumnIndex);
234      }
[2669]235    }
[2676]236    private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
237      dataGridView.Rows[e.RowIndex].ErrorText = string.Empty;
238    }
[3312]239    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) {
[3324]240      int rowIndex = virtualRowIndizes[e.RowIndex];
241      e.Value = Content.GetValue(rowIndex, e.ColumnIndex);
[3312]242    }
243
244    private void dataGridView_Scroll(object sender, ScrollEventArgs e) {
245      UpdateRowHeaders();
246    }
247
248    private void dataGridView_Resize(object sender, EventArgs e) {
249      UpdateRowHeaders();
250    }
[3314]251
252    private void dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
[3320]253      if (Content != null) {
254        if (e.Button == MouseButtons.Left && Content.SortableView) {
255          bool addToSortedIndizes = (Control.ModifierKeys & Keys.Control) == Keys.Control;
256          SortOrder newSortOrder = SortOrder.Ascending;
257          if (sortedColumnIndizes.Any(x => x.Key == e.ColumnIndex)) {
258            SortOrder oldSortOrder = sortedColumnIndizes.Where(x => x.Key == e.ColumnIndex).First().Value;
259            int enumLength = Enum.GetValues(typeof(SortOrder)).Length;
260            newSortOrder = oldSortOrder = (SortOrder)Enum.Parse(typeof(SortOrder), ((((int)oldSortOrder) + 1) % enumLength).ToString());
261          }
[3314]262
[3320]263          if (!addToSortedIndizes)
264            sortedColumnIndizes.Clear();
[3314]265
[3320]266          if (sortedColumnIndizes.Any(x => x.Key == e.ColumnIndex)) {
267            int sortedIndex = sortedColumnIndizes.FindIndex(x => x.Key == e.ColumnIndex);
268            if (newSortOrder != SortOrder.None)
269              sortedColumnIndizes[sortedIndex] = new KeyValuePair<int, SortOrder>(e.ColumnIndex, newSortOrder);
270            else
271              sortedColumnIndizes.RemoveAt(sortedIndex);
272          } else
273            if (newSortOrder != SortOrder.None)
274              sortedColumnIndizes.Add(new KeyValuePair<int, SortOrder>(e.ColumnIndex, newSortOrder));
275          Sort();
276        } else if (e.Button == MouseButtons.Right) {
277          if (Content.ColumnNames.Count() != 0)
278            contextMenu.Show(MousePosition);
279        }
[3314]280      }
281    }
282
283    private void Sort() {
[3328]284      int[] newSortedIndex = Enumerable.Range(0, Content.Rows).ToArray();
[3314]285      if (sortedColumnIndizes.Count != 0) {
286        rowComparer.sortedIndizes = sortedColumnIndizes;
287        rowComparer.matrix = Content;
288        Array.Sort(newSortedIndex, rowComparer);
289      }
290      virtualRowIndizes = newSortedIndex;
[3328]291      UpdateSortGlyph();
[3314]292      dataGridView.Invalidate();
[3328]293    }
294
295    private void UpdateSortGlyph() {
[3314]296      foreach (DataGridViewColumn col in this.dataGridView.Columns)
297        col.HeaderCell.SortGlyphDirection = SortOrder.None;
298      foreach (KeyValuePair<int, SortOrder> p in sortedColumnIndizes)
299        this.dataGridView.Columns[p.Key].HeaderCell.SortGlyphDirection = p.Value;
300    }
[2677]301    #endregion
[3312]302
[3314]303    private class RowComparer : IComparer<int> {
304      public List<KeyValuePair<int, SortOrder>> sortedIndizes;
305      public IStringConvertibleMatrix matrix;
306      public RowComparer() {
307      }
[3312]308
[3314]309      public int Compare(int x, int y) {
310        int result = 0;
311        double double1, double2;
312        DateTime dateTime1, dateTime2;
313        string string1, string2;
314
315        foreach (KeyValuePair<int, SortOrder> pair in sortedIndizes) {
316          string1 = matrix.GetValue(x, pair.Key);
317          string2 = matrix.GetValue(y, pair.Key);
318          if (double.TryParse(string1, out double1) && double.TryParse(string2, out double2))
319            result = double1.CompareTo(double2);
320          else if (DateTime.TryParse(string1, out dateTime1) && DateTime.TryParse(string2, out dateTime2))
321            result = dateTime1.CompareTo(dateTime2);
322          else {
323            if (string1 != null)
324              result = string1.CompareTo(string2);
325            else if (string2 != null)
326              result = string2.CompareTo(string1) * -1;
327          }
328          if (pair.Value == SortOrder.Descending)
329            result *= -1;
330          if (result != 0)
331            return result;
332        }
333        return result;
334      }
335    }
[3316]336
337    private void ShowHideColumns_Click(object sender, EventArgs e) {
338      new ColumnsVisibilityDialog(this.dataGridView.Columns.Cast<DataGridViewColumn>()).ShowDialog();
339    }
[2669]340  }
341}
Note: See TracBrowser for help on using the repository browser.