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, 13 years ago

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

File size: 13.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
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;
24using System.Collections.Generic;
25using System.Drawing;
26using System.Linq;
27using System.Windows.Forms;
28using HeuristicLab.Common;
29using HeuristicLab.MainForm;
30using HeuristicLab.MainForm.WindowsForms;
31
32namespace HeuristicLab.Data.Views {
33  [View("StringConvertibleMatrix View")]
34  [Content(typeof(IStringConvertibleMatrix), true)]
35  public partial class StringConvertibleMatrixView : AsynchronousContentView {
36    public new IStringConvertibleMatrix Content {
37      get { return (IStringConvertibleMatrix)base.Content; }
38      set { base.Content = value; }
39    }
40
41    private int[] virtualRowIndizes;
42    private List<KeyValuePair<int, SortOrder>> sortedColumnIndizes;
43    RowComparer rowComparer;
44
45    public StringConvertibleMatrixView() {
46      InitializeComponent();
47      Caption = "StringConvertibleMatrix View";
48      errorProvider.SetIconAlignment(rowsTextBox, ErrorIconAlignment.MiddleLeft);
49      errorProvider.SetIconPadding(rowsTextBox, 2);
50      errorProvider.SetIconAlignment(columnsTextBox, ErrorIconAlignment.MiddleLeft);
51      errorProvider.SetIconPadding(columnsTextBox, 2);
52      sortedColumnIndizes = new List<KeyValuePair<int, SortOrder>>();
53      rowComparer = new RowComparer();
54    }
55    public StringConvertibleMatrixView(IStringConvertibleMatrix content)
56      : this() {
57      Content = content;
58    }
59
60    protected override void DeregisterContentEvents() {
61      Content.ItemChanged -= new EventHandler<EventArgs<int, int>>(Content_ItemChanged);
62      Content.Reset -= new EventHandler(Content_Reset);
63      Content.ColumnNamesChanged -= new EventHandler(Content_ColumnNamesChanged);
64      Content.RowNamesChanged -= new EventHandler(Content_RowNamesChanged);
65      Content.ReadOnlyViewChanged -= new EventHandler(Content_ReadOnlyViewChanged);
66      base.DeregisterContentEvents();
67    }
68
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);
73      Content.ColumnNamesChanged += new EventHandler(Content_ColumnNamesChanged);
74      Content.RowNamesChanged += new EventHandler(Content_RowNamesChanged);
75      Content.ReadOnlyViewChanged += new EventHandler(Content_ReadOnlyViewChanged);
76    }
77
78
79    protected override void OnContentChanged() {
80      base.OnContentChanged();
81      if (Content == null) {
82        Caption = "StringConvertibleMatrix View";
83        rowsTextBox.Text = "";
84        rowsTextBox.Enabled = false;
85        columnsTextBox.Text = "";
86        columnsTextBox.Enabled = false;
87        dataGridView.Rows.Clear();
88        dataGridView.Columns.Clear();
89        dataGridView.Enabled = false;
90        virtualRowIndizes = new int[0];
91      } else {
92        Caption = "StringConvertibleMatrix (" + Content.GetType().Name + ")";
93        UpdateReadOnlyControls();
94        UpdateData();
95      }
96    }
97
98    private void UpdateData() {
99      sortedColumnIndizes.Clear();
100      Sort();
101      rowsTextBox.Text = Content.Rows.ToString();
102      rowsTextBox.Enabled = true;
103      columnsTextBox.Text = Content.Columns.ToString();
104      columnsTextBox.Enabled = true;
105      virtualRowIndizes = Enumerable.Range(0, Content.Rows).ToArray();
106      dataGridView.RowCount = Content.Rows;
107      dataGridView.ColumnCount = Content.Columns;
108      UpdateRowHeaders();
109      UpdateColumnHeaders();
110      dataGridView.Enabled = true;
111    }
112
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);
127        else
128          dataGridView.Rows[i].HeaderCell.Value = i.ToString();
129      }
130      dataGridView.Invalidate();
131    }
132
133    private void UpdateReadOnlyControls() {
134      dataGridView.ReadOnly = Content.ReadOnlyView;
135      rowsTextBox.ReadOnly = Content.ReadOnlyView;
136      columnsTextBox.ReadOnly = Content.ReadOnlyView;
137    }
138
139    private void Content_RowNamesChanged(object sender, EventArgs e) {
140      if (InvokeRequired)
141        Invoke(new EventHandler(Content_RowNamesChanged), sender, e);
142      else
143        UpdateRowHeaders();
144    }
145    private void Content_ColumnNamesChanged(object sender, EventArgs e) {
146      if (InvokeRequired)
147        Invoke(new EventHandler(Content_ColumnNamesChanged), sender, e);
148      else
149        UpdateColumnHeaders();
150    }
151    private void Content_ItemChanged(object sender, EventArgs<int, int> e) {
152      if (InvokeRequired)
153        Invoke(new EventHandler<EventArgs<int, int>>(Content_ItemChanged), sender, e);
154      else
155        dataGridView.InvalidateCell(e.Value, e.Value2);
156    }
157    private void Content_Reset(object sender, EventArgs e) {
158      if (InvokeRequired)
159        Invoke(new EventHandler(Content_Reset), sender, e);
160      else
161        UpdateData();
162    }
163
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
171    #region TextBox Events
172    private void rowsTextBox_Validating(object sender, CancelEventArgs e) {
173      int i = 0;
174      if (!int.TryParse(rowsTextBox.Text, out i) || (i < 0)) {
175        e.Cancel = true;
176        errorProvider.SetError(rowsTextBox, "Invalid Number of Rows (Valid Values: Positive Integers Larger or Equal to 0)");
177        rowsTextBox.SelectAll();
178      }
179    }
180    private void rowsTextBox_Validated(object sender, EventArgs e) {
181      int textBoxValue = int.Parse(rowsTextBox.Text);
182      if (textBoxValue != Content.Rows)
183        Content.Rows = textBoxValue;
184      errorProvider.SetError(rowsTextBox, string.Empty);
185    }
186    private void rowsTextBox_KeyDown(object sender, KeyEventArgs e) {
187      if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
188        rowsLabel.Focus();  // set focus on label to validate data
189      if (e.KeyCode == Keys.Escape) {
190        rowsTextBox.Text = Content.Rows.ToString();
191        rowsLabel.Focus();  // set focus on label to validate data
192      }
193    }
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;
198        errorProvider.SetError(columnsTextBox, "Invalid Number of Columns (Valid Values: Positive Integers Larger or Equal to 0)");
199        columnsTextBox.SelectAll();
200      }
201    }
202    private void columnsTextBox_Validated(object sender, EventArgs e) {
203      int textBoxValue = int.Parse(columnsTextBox.Text);
204      if (textBoxValue != Content.Columns)
205        Content.Columns = textBoxValue;
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) {
212        columnsTextBox.Text = Content.Columns.ToString();
213        columnsLabel.Focus();  // set focus on label to validate data
214      }
215    }
216    #endregion
217
218    #region DataGridView Events
219    private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
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        }
226      }
227    }
228    private void dataGridView_CellParsing(object sender, DataGridViewCellParsingEventArgs e) {
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      }
235    }
236    private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
237      dataGridView.Rows[e.RowIndex].ErrorText = string.Empty;
238    }
239    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) {
240      int rowIndex = virtualRowIndizes[e.RowIndex];
241      e.Value = Content.GetValue(rowIndex, e.ColumnIndex);
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    }
251
252    private void dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
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          }
262
263          if (!addToSortedIndizes)
264            sortedColumnIndizes.Clear();
265
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        }
280      }
281    }
282
283    private void Sort() {
284      int[] newSortedIndex = Enumerable.Range(0, Content.Rows).ToArray();
285      if (sortedColumnIndizes.Count != 0) {
286        rowComparer.sortedIndizes = sortedColumnIndizes;
287        rowComparer.matrix = Content;
288        Array.Sort(newSortedIndex, rowComparer);
289      }
290      virtualRowIndizes = newSortedIndex;
291      UpdateSortGlyph();
292      dataGridView.Invalidate();
293    }
294
295    private void UpdateSortGlyph() {
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    }
301    #endregion
302
303    private class RowComparer : IComparer<int> {
304      public List<KeyValuePair<int, SortOrder>> sortedIndizes;
305      public IStringConvertibleMatrix matrix;
306      public RowComparer() {
307      }
308
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    }
336
337    private void ShowHideColumns_Click(object sender, EventArgs e) {
338      new ColumnsVisibilityDialog(this.dataGridView.Columns.Cast<DataGridViewColumn>()).ShowDialog();
339    }
340  }
341}
Note: See TracBrowser for help on using the repository browser.