Free cookie consent management tool by TermsFeed Policy Generator

source: branches/DataPreprocessing/HeuristicLab.DataPreprocessing.Views/3.3/DataGridContentView.cs @ 10852

Last change on this file since 10852 was 10852, checked in by rstoll, 10 years ago
  • Search improved

take into account the selected cell when starting a search
updating data during search
updating data when dialog is closed and opened
changed selection during search from highlighting to actual selection (benefit, line chart will be selected according the search)

File size: 19.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 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.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.Windows.Forms;
27using HeuristicLab.Data;
28using HeuristicLab.DataPreprocessing.Filter;
29using HeuristicLab.MainForm;
30
31namespace HeuristicLab.DataPreprocessing.Views {
32  [View("Data Grid Content View")]
33  [Content(typeof(IDataGridContent), true)]
34  public partial class DataGridContentView : CopyOfStringConvertibleMatrixView {
35
36    private bool notOwnEvent = true;
37    private SearchAndReplaceDialog findAndReplaceDialog;
38    private IFindPreprocessingItemsIterator searchIterator;
39    private string currentSearchText;
40    private Tuple<int, int> currentCell;
41
42    public new IDataGridContent Content {
43      get { return (IDataGridContent)base.Content; }
44      set { base.Content = value; }
45    }
46
47    private IList<int> _highlightedRowIndices;
48    public IList<int> HighlightedRowIndices {
49      get { return _highlightedRowIndices; }
50      set {
51        _highlightedRowIndices = value;
52        Refresh();
53      }
54    }
55
56    private IDictionary<int, IList<int>> _highlightedCells;
57    public IDictionary<int, IList<int>> HightlightedCells {
58      get { return _highlightedCells; }
59      set {
60        _highlightedCells = value;
61        Refresh();
62      }
63    }
64
65    private IDictionary<int, IList<int>> _highlightedCellsBackground;
66    public IDictionary<int, IList<int>> HightlightedCellsBackground {
67      get { return _highlightedCellsBackground; }
68      set {
69        _highlightedCellsBackground = value;
70        Refresh();
71      }
72    }
73
74    public DataGridContentView() {
75      InitializeComponent();
76      dataGridView.CellMouseClick += dataGridView_CellMouseClick;
77      dataGridView.CellPainting += new System.Windows.Forms.DataGridViewCellPaintingEventHandler(dataGridView_CellPainting);
78      dataGridView.KeyDown += dataGridView_KeyDown;
79      contextMenuCell.Items.Add(ShowHideColumns);
80      _highlightedCells = new Dictionary<int, IList<int>>();
81      _highlightedRowIndices = new List<int>();
82      _highlightedCellsBackground = new Dictionary<int, IList<int>>();
83      currentCell = null;
84      DataGridView.SelectionChanged += DataGridView_SelectionChanged;
85    }
86
87    void DataGridView_SelectionChanged(object sender, EventArgs e) {
88      if (Content != null) {
89        Content.DataGridLogic.SetSelection(GetSelectedCells());
90        if (AreMultipleCellsSelected()) {
91          ResetHighlightedCellsBackground();
92          HightlightedCellsBackground = GetSelectedCells();
93          searchIterator = null;
94        }
95      }
96    }
97
98    protected override void OnContentChanged() {
99      base.OnContentChanged();
100      if (Content == null && findAndReplaceDialog != null) {
101        findAndReplaceDialog.Close();
102      }
103    }
104
105    protected override void RegisterContentEvents() {
106      base.RegisterContentEvents();
107      Content.Changed += Content_Changed;
108    }
109
110    protected override void DeregisterContentEvents() {
111      base.DeregisterContentEvents();
112      Content.Changed -= Content_Changed;
113    }
114
115    void Content_Changed(object sender, DataPreprocessingChangedEventArgs e) {
116      if (notOwnEvent) {
117        switch (e.Type) {
118          case DataPreprocessingChangedEventType.ChangeColumn:
119          case DataPreprocessingChangedEventType.ChangeItem:
120            dataGridView.Refresh();
121            break;
122          default:
123            OnContentChanged();
124            break;
125        }
126      }
127      searchIterator = null;
128    }
129
130    protected override void dataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) {
131      if (!dataGridView.ReadOnly) {
132        string errorMessage;
133        if (Content != null && !Content.DataGridLogic.Validate(e.FormattedValue.ToString(), out errorMessage, e.ColumnIndex)) {
134          e.Cancel = true;
135          dataGridView.Rows[e.RowIndex].ErrorText = errorMessage;
136        }
137      }
138    }
139
140    protected override void dataGridView_CellParsing(object sender, DataGridViewCellParsingEventArgs e) {
141      triggersOwnEvent(() => base.dataGridView_CellParsing(sender, e));
142    }
143
144    protected override void PasteValuesToDataGridView() {
145      triggersOwnEvent(() => base.PasteValuesToDataGridView());
146    }
147
148    protected override void SetEnabledStateOfControls() {
149      base.SetEnabledStateOfControls();
150      rowsTextBox.ReadOnly = true;
151      columnsTextBox.ReadOnly = true;
152    }
153
154    private void btnApplySort_Click(object sender, System.EventArgs e) {
155      triggersOwnEvent(() => {
156        Content.ManipulationLogic.ReOrderToIndices(virtualRowIndices);
157        OnContentChanged();
158      });
159    }
160
161    private void triggersOwnEvent(Action action) {
162      notOwnEvent = false;
163      action();
164      notOwnEvent = true;
165    }
166
167    #region FindAndReplaceDialog
168
169    private void CreateFindAndReplaceDialog() {
170      findAndReplaceDialog = new SearchAndReplaceDialog();
171      findAndReplaceDialog.Show(this);
172      if (AreMultipleCellsSelected()) {
173        HightlightedCellsBackground = GetSelectedCells();
174        dataGridView.ClearSelection();
175      }
176      findAndReplaceDialog.FindAllEvent += findAndReplaceDialog_FindAllEvent;
177      findAndReplaceDialog.FindNextEvent += findAndReplaceDialog_FindNextEvent;
178      findAndReplaceDialog.ReplaceAllEvent += findAndReplaceDialog_ReplaceAllEvent;
179      findAndReplaceDialog.ReplaceNextEvent += findAndReplaceDialog_ReplaceEvent;
180      findAndReplaceDialog.FormClosing += findAndReplaceDialog_FormClosing;
181      searchIterator = null;
182    }
183
184    void findAndReplaceDialog_FormClosing(object sender, FormClosingEventArgs e) {
185      ResetHighlightedCells();
186      ResetHighlightedCellsBackground();
187      searchIterator = null;
188    }
189
190    void findAndReplaceDialog_ReplaceEvent(object sender, EventArgs e) {
191      if (searchIterator != null && searchIterator.GetCurrent() != null) {
192        Replace(TransformToDictionary(currentCell));
193      }
194    }
195
196    void findAndReplaceDialog_ReplaceAllEvent(object sender, EventArgs e) {
197      Replace(FindAll(findAndReplaceDialog.GetSearchText()));
198    }
199
200    void findAndReplaceDialog_FindNextEvent(object sender, EventArgs e) {
201      if (searchIterator == null || currentSearchText != findAndReplaceDialog.GetSearchText()) {
202        searchIterator = new FindPreprocessingItemsIterator(FindAll(findAndReplaceDialog.GetSearchText()));
203        currentSearchText = findAndReplaceDialog.GetSearchText();
204      }
205      if (IsOneCellSelected()) {
206        var first = GetSelectedCells().First();
207        searchIterator.SetStartCell(first.Key, first.Value[0]);
208      }
209
210
211      bool moreOccurences = false;
212      do {
213        currentCell = searchIterator.GetCurrent();
214        moreOccurences = searchIterator.MoveNext();
215        if (IsOneCellSelected()) {
216          var first = GetSelectedCells().First();
217          if (currentCell.Item1 == first.Key && currentCell.Item2 == first.Value[0]) {
218            if (!moreOccurences) {
219              searchIterator.Reset();
220            }
221            currentCell = searchIterator.GetCurrent();
222            moreOccurences = searchIterator.MoveNext();
223
224          }
225        }
226      } while (moreOccurences && (currentCell == null || !Content.GetValue(currentCell.Item2, currentCell.Item1).Equals(currentSearchText)));
227
228      if (currentCell != null) {
229        dataGridView.ClearSelection();
230        dataGridView[currentCell.Item1, currentCell.Item2].Selected = true;
231      } else {
232        ResetHighlightedCells();
233      }
234
235      //if (!moreOccurences) {
236      //  searchIterator.Reset();
237      //  dataGridView.ClearSelection();
238      //  currentCell = searchIterator.GetCurrent();
239      //  dataGridView[currentCell.Item1, currentCell.Item2].Selected = true;
240      //}
241    }
242
243    private bool AreMultipleCellsSelected() {
244      return GetSelectedCellCount() > 1;
245    }
246
247    private bool IsOneCellSelected() {
248      return GetSelectedCellCount() == 1;
249    }
250
251    private int GetSelectedCellCount() {
252      int count = 0;
253      foreach (var column in GetSelectedCells()) {
254        count += column.Value.Count();
255      }
256      return count;
257    }
258
259    void findAndReplaceDialog_FindAllEvent(object sender, EventArgs e) {
260      HightlightedCells = FindAll(findAndReplaceDialog.GetSearchText());
261    }
262
263    private IDictionary<int, IList<int>> FindAll(string match) {
264      bool searchInSelection = HightlightedCellsBackground.Values.Sum(list => list.Count) > 1;
265      var comparisonFilter = new ComparisonFilter(Content.FilterLogic.PreprocessingData, Core.ConstraintOperation.Equal, new StringValue(match), true);
266      var filters = new List<Filter.IFilter>() { comparisonFilter };
267      var foundCells = new Dictionary<int, IList<int>>();
268      for (int i = 0; i < Content.FilterLogic.PreprocessingData.Columns; i++) {
269        comparisonFilter.ConstraintColumn = i;
270        bool[] filteredRows = Content.FilterLogic.GetFilterResult(filters, true);
271        var foundIndices = new List<int>();
272        for (int idx = 0; idx < filteredRows.Length; ++idx) {
273          var notFilteredThusFound = !filteredRows[idx];
274          if (notFilteredThusFound) {
275            foundIndices.Add(idx);
276          }
277        }
278        foundCells[i] = foundIndices;
279        IList<int> selectedList;
280        if (searchInSelection && HightlightedCellsBackground.TryGetValue(i, out selectedList)) {
281          foundCells[i] = foundCells[i].Intersect(selectedList).ToList<int>();
282        } else if (searchInSelection) {
283          foundCells[i].Clear();
284        }
285      }
286      return foundCells;
287    }
288
289    private void Replace(IDictionary<int, IList<int>> cells) {
290      if (findAndReplaceDialog != null) {
291        switch (findAndReplaceDialog.GetReplaceAction()) {
292          case ReplaceAction.Value:
293            Content.ManipulationLogic.ReplaceIndicesByValue(cells, findAndReplaceDialog.GetReplaceText());
294            break;
295          case ReplaceAction.Average:
296            Content.ManipulationLogic.ReplaceIndicesByAverageValue(cells, false);
297            break;
298          case ReplaceAction.Median:
299            Content.ManipulationLogic.ReplaceIndicesByMedianValue(cells, false);
300            break;
301          case ReplaceAction.Random:
302            Content.ManipulationLogic.ReplaceIndicesByRandomValue(cells, false);
303            break;
304          case ReplaceAction.MostCommon:
305            Content.ManipulationLogic.ReplaceIndicesByMostCommonValue(cells, false);
306            break;
307          case ReplaceAction.Interpolation:
308            Content.ManipulationLogic.ReplaceIndicesByLinearInterpolationOfNeighbours(cells);
309            break;
310        }
311      }
312    }
313
314    private IDictionary<int, IList<int>> TransformToDictionary(Tuple<int, int> tuple) {
315      var highlightCells = new Dictionary<int, IList<int>>();
316      highlightCells.Add(tuple.Item1, new List<int>() { tuple.Item2 });
317      return highlightCells;
318    }
319
320    private void ResetHighlightedCells() {
321      HightlightedCells = new Dictionary<int, IList<int>>();
322    }
323
324    private void ResetHighlightedCellsBackground() {
325      HightlightedCellsBackground = new Dictionary<int, IList<int>>();
326    }
327
328    #endregion FindAndReplaceDialog
329
330    private void dataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
331      if (Content == null) return;
332      if (e.Button == System.Windows.Forms.MouseButtons.Right) {
333        if (e.ColumnIndex == -1 || e.RowIndex == -1) {
334          replaceValueOverColumnToolStripMenuItem.Visible = false;
335          contextMenuCell.Show(MousePosition);
336        } else {
337          if (!dataGridView.SelectedCells.Contains(dataGridView[e.ColumnIndex, e.RowIndex])) {
338            dataGridView.ClearSelection();
339            dataGridView[e.ColumnIndex, e.RowIndex].Selected = true;
340          }
341
342          var columnIndices = new HashSet<int>();
343          for (int i = 0; i < dataGridView.SelectedCells.Count; i++) {
344            columnIndices.Add(dataGridView.SelectedCells[i].ColumnIndex);
345          }
346          averageToolStripMenuItem_Column.Enabled =
347            averageToolStripMenuItem_Selection.Enabled =
348            medianToolStripMenuItem_Column.Enabled =
349            medianToolStripMenuItem_Selection.Enabled =
350            randomToolStripMenuItem_Column.Enabled =
351            randomToolStripMenuItem_Selection.Enabled = !Content.DataGridLogic.AreAllStringColumns(columnIndices);
352
353          smoothingToolStripMenuItem_Column.Enabled =
354            interpolationToolStripMenuItem_Column.Enabled = !dataGridView.SelectedCells.Contains(dataGridView[e.ColumnIndex, 0])
355            && !dataGridView.SelectedCells.Contains(dataGridView[e.ColumnIndex, Content.Rows - 1])
356            && !Content.DataGridLogic.AreAllStringColumns(columnIndices);
357
358          replaceValueOverColumnToolStripMenuItem.Visible = true;
359          contextMenuCell.Show(MousePosition);
360        }
361      }
362    }
363
364    protected void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) {
365      if (Content == null) return;
366      if (e.RowIndex < 0) return;
367      if (e.ColumnIndex < 0) return;
368      if (e.State.HasFlag(DataGridViewElementStates.Selected)) return;
369      if (!e.PaintParts.HasFlag(DataGridViewPaintParts.Background)) return;
370      if (HighlightedRowIndices == null && HightlightedCells == null) return;
371
372      int rowIndex = virtualRowIndices[e.RowIndex];
373
374      Color backColor = e.CellStyle.BackColor;
375
376      if (HightlightedCellsBackground.ContainsKey(e.ColumnIndex) && HightlightedCellsBackground[e.ColumnIndex].Contains(e.RowIndex)) {
377        backColor = Color.LightGray;
378      }
379      if (HighlightedRowIndices.Contains(rowIndex) || HightlightedCells.ContainsKey(e.ColumnIndex) && HightlightedCells[e.ColumnIndex].Contains(e.RowIndex)) {
380        backColor = Color.LightGreen;
381      }
382
383      using (Brush backColorBrush = new SolidBrush(backColor)) {
384        Rectangle bounds = new Rectangle(e.CellBounds.X, e.CellBounds.Y, e.CellBounds.Width, e.CellBounds.Height);
385        e.Graphics.FillRectangle(backColorBrush, bounds);
386      }
387
388      using (Brush gridBrush = new SolidBrush(Color.LightGray)) {
389        Pen gridLinePen = new Pen(gridBrush);
390        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left,
391               e.CellBounds.Bottom - 1, e.CellBounds.Right - 1,
392               e.CellBounds.Bottom - 1);
393        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1,
394            e.CellBounds.Top, e.CellBounds.Right - 1,
395            e.CellBounds.Bottom);
396      }
397
398      e.PaintContent(e.CellBounds);
399      e.Handled = true;
400    }
401
402    void dataGridView_KeyDown(object sender, KeyEventArgs e) {
403      var selectedRows = dataGridView.SelectedRows;
404      if (e.KeyCode == Keys.Delete && selectedRows.Count > 0) {
405        List<int> rows = new List<int>();
406        for (int i = 0; i < selectedRows.Count; ++i) {
407          rows.Add(selectedRows[i].Index);
408        }
409        triggersOwnEvent(() => {
410          Content.DataGridLogic.DeleteRow(rows);
411          OnContentChanged();
412        });
413      } else if (e.Control && e.KeyCode == Keys.F) {
414        CreateFindAndReplaceDialog();
415        findAndReplaceDialog.ActivateSearch();
416      } else if (e.Control && e.KeyCode == Keys.R) {
417        CreateFindAndReplaceDialog();
418        findAndReplaceDialog.ActivateReplace();
419      }
420    }
421
422    protected override int[] Sort(IEnumerable<KeyValuePair<int, SortOrder>> sortedColumns) {
423      btnApplySort.Enabled = sortedColumns.Any();
424      return base.Sort(sortedColumns);
425    }
426
427    protected override void ClearSorting() {
428      btnApplySort.Enabled = false;
429      base.ClearSorting();
430    }
431
432    private IDictionary<int, IList<int>> GetSelectedCells() {
433      IDictionary<int, IList<int>> selectedCells = new Dictionary<int, IList<int>>();
434      for (int i = 0; i < dataGridView.SelectedCells.Count; i++) {
435        var columnIndex = dataGridView.SelectedCells[i].ColumnIndex;
436        if (!selectedCells.ContainsKey(columnIndex)) {
437          selectedCells.Add(columnIndex, new List<int>());
438        }
439        selectedCells[columnIndex].Add(dataGridView.SelectedCells[i].RowIndex);
440      }
441      return selectedCells;
442    }
443
444    private void ReplaceWithAverage_Column_Click(object sender, EventArgs e) {
445      Content.ManipulationLogic.ReplaceIndicesByAverageValue(GetSelectedCells(), false);
446    }
447    private void ReplaceWithAverage_Selection_Click(object sender, EventArgs e) {
448      Content.ManipulationLogic.ReplaceIndicesByAverageValue(GetSelectedCells(), true);
449    }
450
451    private void ReplaceWithMedian_Column_Click(object sender, EventArgs e) {
452      Content.ManipulationLogic.ReplaceIndicesByMedianValue(GetSelectedCells(), false);
453    }
454    private void ReplaceWithMedian_Selection_Click(object sender, EventArgs e) {
455      Content.ManipulationLogic.ReplaceIndicesByMedianValue(GetSelectedCells(), true);
456    }
457
458    private void ReplaceWithRandom_Column_Click(object sender, EventArgs e) {
459      Content.ManipulationLogic.ReplaceIndicesByRandomValue(GetSelectedCells(), false);
460    }
461    private void ReplaceWithRandom_Selection_Click(object sender, EventArgs e) {
462      Content.ManipulationLogic.ReplaceIndicesByRandomValue(GetSelectedCells(), true);
463    }
464
465    private void ReplaceWithMostCommon_Column_Click(object sender, EventArgs e) {
466      Content.ManipulationLogic.ReplaceIndicesByMostCommonValue(GetSelectedCells(), false);
467    }
468    private void ReplaceWithMostCommon_Selection_Click(object sender, EventArgs e) {
469      Content.ManipulationLogic.ReplaceIndicesByMostCommonValue(GetSelectedCells(), true);
470    }
471
472    private void ReplaceWithInterpolation_Column_Click(object sender, EventArgs e) {
473      Content.ManipulationLogic.ReplaceIndicesByLinearInterpolationOfNeighbours(GetSelectedCells());
474    }
475
476    private void ReplaceWithSmoothing_Selection_Click(object sender, EventArgs e) {
477      Content.ManipulationLogic.ReplaceIndicesBySmoothing(GetSelectedCells());
478    }
479
480    private void btnSearch_Click(object sender, EventArgs e) {
481      CreateFindAndReplaceDialog();
482      findAndReplaceDialog.ActivateSearch();
483    }
484
485    private void btnReplace_Click(object sender, EventArgs e) {
486      CreateFindAndReplaceDialog();
487      findAndReplaceDialog.ActivateReplace();
488    }
489  }
490}
Note: See TracBrowser for help on using the repository browser.