Free cookie consent management tool by TermsFeed Policy Generator

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

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

implemented first version of View.ReadOnly and adapted some views to the new mechanism (ticket #973)

File size: 15.3 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        columnsTextBox.Text = "";
85        dataGridView.Rows.Clear();
86        dataGridView.Columns.Clear();
87        virtualRowIndizes = new int[0];
88      } else {
89        Caption = "StringConvertibleMatrix (" + Content.GetType().Name + ")";
90        UpdateData();
91      }
92      SetEnableStateOfControls();
93    }
94    protected override void OnReadOnlyChanged() {
95      base.OnReadOnlyChanged();
96      SetEnableStateOfControls();
97    }
98    private void SetEnableStateOfControls() {
99      if (Content == null) {
100        rowsTextBox.Enabled = false;
101        columnsTextBox.Enabled = false;
102        dataGridView.Enabled = false;
103      } else {
104        rowsTextBox.Enabled = true;
105        columnsTextBox.Enabled = true;
106        dataGridView.Enabled = true;
107        rowsTextBox.ReadOnly = ReadOnly;
108        columnsTextBox.ReadOnly = ReadOnly;
109        dataGridView.ReadOnly = ReadOnly;
110      }
111    }
112
113    private void UpdateData() {
114      sortedColumnIndizes.Clear();
115      Sort();
116      rowsTextBox.Text = Content.Rows.ToString();
117      rowsTextBox.Enabled = true;
118      columnsTextBox.Text = Content.Columns.ToString();
119      columnsTextBox.Enabled = true;
120      virtualRowIndizes = Enumerable.Range(0, Content.Rows).ToArray();
121      //DataGridViews with Rows but no columns are not allowed !
122      if (Content.Rows == 0 && dataGridView.RowCount != Content.Rows && !Content.ReadOnlyView)
123        Content.Rows = dataGridView.RowCount;
124      else
125        dataGridView.RowCount = Content.Rows;
126      if (Content.Columns == 0 && dataGridView.ColumnCount != Content.Columns && !Content.ReadOnlyView)
127        Content.Columns = dataGridView.ColumnCount;
128      else
129        dataGridView.ColumnCount = Content.Columns;
130
131      UpdateRowHeaders();
132      UpdateColumnHeaders();
133      dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.ColumnHeader);
134      dataGridView.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders);
135      dataGridView.Enabled = true;
136    }
137
138    private void UpdateColumnHeaders() {
139      for (int i = 0; i < Content.Columns; i++) {
140        if (Content.ColumnNames.Count() != 0)
141          dataGridView.Columns[i].HeaderText = Content.ColumnNames.ElementAt(i);
142        else
143          dataGridView.Columns[i].HeaderText = "Column " + (i + 1);
144      }
145      dataGridView.Invalidate();
146    }
147
148    private void UpdateRowHeaders() {
149      for (int i = dataGridView.FirstDisplayedScrollingRowIndex; i < dataGridView.FirstDisplayedScrollingRowIndex + dataGridView.DisplayedRowCount(true); i++) {
150        if (Content.RowNames.Count() != 0)
151          dataGridView.Rows[i].HeaderCell.Value = Content.RowNames.ElementAt(i);
152        else
153          dataGridView.Rows[i].HeaderCell.Value = "Row " + (i + 1);
154      }
155      dataGridView.Invalidate();
156    }
157
158    private void UpdateReadOnlyControls() {
159      dataGridView.ReadOnly = Content.ReadOnlyView;
160      rowsTextBox.ReadOnly = Content.ReadOnlyView;
161      columnsTextBox.ReadOnly = Content.ReadOnlyView;
162    }
163
164    private void Content_RowNamesChanged(object sender, EventArgs e) {
165      if (InvokeRequired)
166        Invoke(new EventHandler(Content_RowNamesChanged), sender, e);
167      else
168        UpdateRowHeaders();
169    }
170    private void Content_ColumnNamesChanged(object sender, EventArgs e) {
171      if (InvokeRequired)
172        Invoke(new EventHandler(Content_ColumnNamesChanged), sender, e);
173      else
174        UpdateColumnHeaders();
175    }
176    private void Content_ItemChanged(object sender, EventArgs<int, int> e) {
177      if (InvokeRequired)
178        Invoke(new EventHandler<EventArgs<int, int>>(Content_ItemChanged), sender, e);
179      else
180        dataGridView.InvalidateCell(e.Value2, e.Value);
181    }
182    private void Content_Reset(object sender, EventArgs e) {
183      if (InvokeRequired)
184        Invoke(new EventHandler(Content_Reset), sender, e);
185      else
186        UpdateData();
187    }
188
189    private void Content_ReadOnlyViewChanged(object sender, EventArgs e) {
190      if (InvokeRequired)
191        Invoke(new EventHandler(Content_ReadOnlyViewChanged), sender, e);
192      else
193        UpdateReadOnlyControls();
194    }
195
196    #region TextBox Events
197    private void rowsTextBox_Validating(object sender, CancelEventArgs e) {
198      int i = 0;
199      if (!int.TryParse(rowsTextBox.Text, out i) || (i <= 0)) {
200        e.Cancel = true;
201        errorProvider.SetError(rowsTextBox, "Invalid Number of Rows (Valid values are positive integers larger than 0)");
202        rowsTextBox.SelectAll();
203      }
204    }
205    private void rowsTextBox_Validated(object sender, EventArgs e) {
206      int textBoxValue = int.Parse(rowsTextBox.Text);
207      if (textBoxValue != Content.Rows)
208        Content.Rows = textBoxValue;
209      errorProvider.SetError(rowsTextBox, string.Empty);
210    }
211    private void rowsTextBox_KeyDown(object sender, KeyEventArgs e) {
212      if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
213        rowsLabel.Focus();  // set focus on label to validate data
214      if (e.KeyCode == Keys.Escape) {
215        rowsTextBox.Text = Content.Rows.ToString();
216        rowsLabel.Focus();  // set focus on label to validate data
217      }
218    }
219    private void columnsTextBox_Validating(object sender, CancelEventArgs e) {
220      int i = 0;
221      if (!int.TryParse(columnsTextBox.Text, out i) || (i <= 0)) {
222        e.Cancel = true;
223        errorProvider.SetError(columnsTextBox, "Invalid Number of Columns (Valid values are positive integers larger than 0)");
224        columnsTextBox.SelectAll();
225      }
226    }
227    private void columnsTextBox_Validated(object sender, EventArgs e) {
228      int textBoxValue = int.Parse(columnsTextBox.Text);
229      if (textBoxValue != Content.Columns)
230        Content.Columns = textBoxValue;
231      errorProvider.SetError(columnsTextBox, string.Empty);
232    }
233    private void columnsTextBox_KeyDown(object sender, KeyEventArgs e) {
234      if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return)
235        columnsLabel.Focus();  // set focus on label to validate data
236      if (e.KeyCode == Keys.Escape) {
237        columnsTextBox.Text = Content.Columns.ToString();
238        columnsLabel.Focus();  // set focus on label to validate data
239      }
240    }
241    #endregion
242
243    #region DataGridView Events
244    private void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
245      if (!dataGridView.ReadOnly) {
246        string errorMessage;
247        if (!Content.Validate(e.FormattedValue.ToString(), out errorMessage)) {
248          e.Cancel = true;
249          dataGridView.Rows[e.RowIndex].ErrorText = errorMessage;
250        }
251      }
252    }
253    private void dataGridView_CellParsing(object sender, DataGridViewCellParsingEventArgs e) {
254      if (!dataGridView.ReadOnly) {
255        string value = e.Value.ToString();
256        int rowIndex = virtualRowIndizes[e.RowIndex];
257        e.ParsingApplied = Content.SetValue(value, rowIndex, e.ColumnIndex);
258        if (e.ParsingApplied) e.Value = Content.GetValue(rowIndex, e.ColumnIndex);
259      }
260    }
261    private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) {
262      dataGridView.Rows[e.RowIndex].ErrorText = string.Empty;
263    }
264    private void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) {
265      if (e.RowIndex < Content.Rows && e.ColumnIndex < Content.Columns) {
266        int rowIndex = virtualRowIndizes[e.RowIndex];
267        e.Value = Content.GetValue(rowIndex, e.ColumnIndex);
268      }
269    }
270    private void dataGridView_Scroll(object sender, ScrollEventArgs e) {
271      UpdateRowHeaders();
272    }
273    private void dataGridView_Resize(object sender, EventArgs e) {
274      UpdateRowHeaders();
275    }
276
277    private void dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
278      if (Content != null) {
279        if (e.Button == MouseButtons.Left && Content.SortableView) {
280          bool addToSortedIndizes = (Control.ModifierKeys & Keys.Control) == Keys.Control;
281          SortOrder newSortOrder = SortOrder.Ascending;
282          if (sortedColumnIndizes.Any(x => x.Key == e.ColumnIndex)) {
283            SortOrder oldSortOrder = sortedColumnIndizes.Where(x => x.Key == e.ColumnIndex).First().Value;
284            int enumLength = Enum.GetValues(typeof(SortOrder)).Length;
285            newSortOrder = oldSortOrder = (SortOrder)Enum.Parse(typeof(SortOrder), ((((int)oldSortOrder) + 1) % enumLength).ToString());
286          }
287
288          if (!addToSortedIndizes)
289            sortedColumnIndizes.Clear();
290
291          if (sortedColumnIndizes.Any(x => x.Key == e.ColumnIndex)) {
292            int sortedIndex = sortedColumnIndizes.FindIndex(x => x.Key == e.ColumnIndex);
293            if (newSortOrder != SortOrder.None)
294              sortedColumnIndizes[sortedIndex] = new KeyValuePair<int, SortOrder>(e.ColumnIndex, newSortOrder);
295            else
296              sortedColumnIndizes.RemoveAt(sortedIndex);
297          } else
298            if (newSortOrder != SortOrder.None)
299              sortedColumnIndizes.Add(new KeyValuePair<int, SortOrder>(e.ColumnIndex, newSortOrder));
300          Sort();
301        } else if (e.Button == MouseButtons.Right) {
302          if (Content.ColumnNames.Count() != 0)
303            contextMenu.Show(MousePosition);
304        }
305      }
306    }
307
308    private void Sort() {
309      int[] newSortedIndex = Enumerable.Range(0, Content.Rows).ToArray();
310      if (sortedColumnIndizes.Count != 0) {
311        rowComparer.SortedIndizes = sortedColumnIndizes;
312        rowComparer.Matrix = Content;
313        Array.Sort(newSortedIndex, rowComparer);
314      }
315      virtualRowIndizes = newSortedIndex;
316      UpdateSortGlyph();
317      dataGridView.Invalidate();
318    }
319
320    private void UpdateSortGlyph() {
321      foreach (DataGridViewColumn col in this.dataGridView.Columns)
322        col.HeaderCell.SortGlyphDirection = SortOrder.None;
323      foreach (KeyValuePair<int, SortOrder> p in sortedColumnIndizes)
324        this.dataGridView.Columns[p.Key].HeaderCell.SortGlyphDirection = p.Value;
325    }
326    #endregion
327
328    public class RowComparer : IComparer<int> {
329      public RowComparer() {
330      }
331
332      private List<KeyValuePair<int, SortOrder>> sortedIndizes;
333      public IEnumerable<KeyValuePair<int, SortOrder>> SortedIndizes {
334        get { return this.sortedIndizes; }
335        set { sortedIndizes = new List<KeyValuePair<int, SortOrder>>(value); }
336      }
337      private IStringConvertibleMatrix matrix;
338      public IStringConvertibleMatrix Matrix {
339        get { return this.matrix; }
340        set { this.matrix = value; }
341      }
342
343      public int Compare(int x, int y) {
344        int result = 0;
345        double double1, double2;
346        DateTime dateTime1, dateTime2;
347        string string1, string2;
348
349        if (matrix == null)
350          throw new InvalidOperationException("Could not sort IStringConvertibleMatrix if the matrix member is null.");
351        if (sortedIndizes == null)
352          return 0;
353
354        foreach (KeyValuePair<int, SortOrder> pair in sortedIndizes.Where(p => p.Value != SortOrder.None)) {
355          string1 = matrix.GetValue(x, pair.Key);
356          string2 = matrix.GetValue(y, pair.Key);
357          if (double.TryParse(string1, out double1) && double.TryParse(string2, out double2))
358            result = double1.CompareTo(double2);
359          else if (DateTime.TryParse(string1, out dateTime1) && DateTime.TryParse(string2, out dateTime2))
360            result = dateTime1.CompareTo(dateTime2);
361          else {
362            if (string1 != null)
363              result = string1.CompareTo(string2);
364            else if (string2 != null)
365              result = string2.CompareTo(string1) * -1;
366          }
367          if (pair.Value == SortOrder.Descending)
368            result *= -1;
369          if (result != 0)
370            return result;
371        }
372        return result;
373      }
374    }
375
376    private void ShowHideColumns_Click(object sender, EventArgs e) {
377      new ColumnsVisibilityDialog(this.dataGridView.Columns.Cast<DataGridViewColumn>()).ShowDialog();
378    }
379  }
380}
Note: See TracBrowser for help on using the repository browser.