Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core.Views/3.3/ItemArrayView.cs @ 5304

Last change on this file since 5304 was 5302, checked in by swagner, 14 years ago

Fixed exception which was thrown when item updates are still pending after the content of an ItemCollectionView has already been changed (#1324)

File size: 19.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.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.Windows.Forms;
27using HeuristicLab.Collections;
28using HeuristicLab.MainForm;
29using HeuristicLab.MainForm.WindowsForms;
30using HeuristicLab.PluginInfrastructure;
31
32namespace HeuristicLab.Core.Views {
33  [View("ItemArray View")]
34  [Content(typeof(ItemArray<>), true)]
35  [Content(typeof(IItemArray<>), false)]
36  public partial class ItemArrayView<T> : ItemView where T : class, IItem {
37    protected Dictionary<T, List<ListViewItem>> itemListViewItemMapping;
38    protected TypeSelectorDialog typeSelectorDialog;
39
40    public new IItemArray<T> Content {
41      get { return (IItemArray<T>)base.Content; }
42      set { base.Content = value; }
43    }
44
45    public ListView ItemsListView {
46      get { return itemsListView; }
47    }
48
49    public ItemArrayView() {
50      InitializeComponent();
51      itemListViewItemMapping = new Dictionary<T, List<ListViewItem>>();
52    }
53
54    protected override void Dispose(bool disposing) {
55      if (disposing) {
56        if (typeSelectorDialog != null) typeSelectorDialog.Dispose();
57        if (components != null) components.Dispose();
58      }
59      base.Dispose(disposing);
60    }
61
62    protected override void DeregisterContentEvents() {
63      Content.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsReplaced);
64      Content.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsMoved);
65      Content.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_CollectionReset);
66      foreach (T item in itemListViewItemMapping.Keys) {
67        DeregisterItemEvents(item);
68      }
69      base.DeregisterContentEvents();
70    }
71    protected override void RegisterContentEvents() {
72      base.RegisterContentEvents();
73      Content.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsReplaced);
74      Content.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsMoved);
75      Content.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_CollectionReset);
76    }
77    protected virtual void DeregisterItemEvents(T item) {
78      item.ItemImageChanged -= new EventHandler(Item_ItemImageChanged);
79      item.ToStringChanged -= new EventHandler(Item_ToStringChanged);
80    }
81    protected virtual void RegisterItemEvents(T item) {
82      item.ItemImageChanged += new EventHandler(Item_ItemImageChanged);
83      item.ToStringChanged += new EventHandler(Item_ToStringChanged);
84    }
85
86    protected override void OnContentChanged() {
87      base.OnContentChanged();
88
89      int selectedIndex = -1;
90      if (itemsListView.SelectedItems.Count == 1) selectedIndex = itemsListView.SelectedIndices[0];
91
92      itemsListView.Items.Clear();
93      itemListViewItemMapping.Clear();
94      RebuildImageList();
95      viewHost.Content = null;
96      if (Content != null) {
97        Caption += " (" + Content.GetType().Name + ")";
98        foreach (T item in Content)
99          AddListViewItem(CreateListViewItem(item));
100        AdjustListViewColumnSizes();
101        if ((selectedIndex != -1) && (selectedIndex < itemsListView.Items.Count))
102          itemsListView.Items[selectedIndex].Selected = true;
103      }
104    }
105
106    protected override void SetEnabledStateOfControls() {
107      base.SetEnabledStateOfControls();
108      if (Content == null) {
109        addButton.Enabled = false;
110        moveUpButton.Enabled = false;
111        moveDownButton.Enabled = false;
112        removeButton.Enabled = false;
113        itemsListView.Enabled = false;
114        detailsGroupBox.Enabled = false;
115      } else {
116        addButton.Enabled = itemsListView.SelectedItems.Count > 0 &&
117                            !Content.IsReadOnly && !ReadOnly;
118        moveUpButton.Enabled = itemsListView.SelectedItems.Count == 1 &&
119                               itemsListView.SelectedIndices[0] != 0 &&
120                               !Content.IsReadOnly && !ReadOnly;
121        moveDownButton.Enabled = itemsListView.SelectedItems.Count == 1 &&
122                                 itemsListView.SelectedIndices[0] != itemsListView.Items.Count - 1 &&
123                                 !Content.IsReadOnly && !ReadOnly;
124        removeButton.Enabled = itemsListView.SelectedItems.Count > 0 &&
125                               !Content.IsReadOnly && !ReadOnly;
126        itemsListView.Enabled = true;
127        detailsGroupBox.Enabled = itemsListView.SelectedItems.Count == 1;
128      }
129    }
130
131    protected virtual T CreateItem() {
132      if (typeSelectorDialog == null) {
133        typeSelectorDialog = new TypeSelectorDialog();
134        typeSelectorDialog.Caption = "Select Item";
135        typeSelectorDialog.TypeSelector.Caption = "Available Items";
136        typeSelectorDialog.TypeSelector.Configure(typeof(T), false, true);
137      }
138
139      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
140        try {
141          return (T)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
142        }
143        catch (Exception ex) {
144          ErrorHandling.ShowErrorDialog(this, ex);
145        }
146      }
147      return null;
148    }
149    protected virtual ListViewItem CreateListViewItem(T item) {
150      ListViewItem listViewItem = new ListViewItem();
151      if (item == null) {
152        listViewItem.Text = "null";
153        itemsListView.SmallImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.Nothing);
154        listViewItem.ImageIndex = itemsListView.SmallImageList.Images.Count - 1;
155      } else {
156        listViewItem.Text = item.ToString();
157        listViewItem.ToolTipText = item.ItemName + ": " + item.ItemDescription;
158        itemsListView.SmallImageList.Images.Add(item.ItemImage);
159        listViewItem.ImageIndex = itemsListView.SmallImageList.Images.Count - 1;
160        listViewItem.Tag = item;
161      }
162      return listViewItem;
163    }
164    protected virtual void AddListViewItem(ListViewItem listViewItem) {
165      T item = (listViewItem.Tag as T);
166      itemsListView.Items.Add(listViewItem);
167      if (item != null) {
168        if (!itemListViewItemMapping.ContainsKey(item)) {
169          RegisterItemEvents(item);
170          itemListViewItemMapping.Add(item, new List<ListViewItem>());
171        }
172        itemListViewItemMapping[item].Add(listViewItem);
173      }
174    }
175    protected virtual void InsertListViewItem(int index, ListViewItem listViewItem) {
176      T item = (listViewItem.Tag as T);
177      itemsListView.Items.Insert(index, listViewItem);
178      if (item != null) {
179        if (!itemListViewItemMapping.ContainsKey(item)) {
180          RegisterItemEvents(item);
181          itemListViewItemMapping.Add(item, new List<ListViewItem>());
182        }
183        itemListViewItemMapping[item].Add(listViewItem);
184      }
185    }
186    protected virtual void RemoveListViewItem(ListViewItem listViewItem) {
187      T item = (listViewItem.Tag as T);
188      if (item != null) {
189        itemListViewItemMapping[item].Remove(listViewItem);
190        if (itemListViewItemMapping[item].Count == 0) {
191          itemListViewItemMapping.Remove(item);
192          DeregisterItemEvents(item);
193        }
194      }
195      listViewItem.Remove();
196    }
197    protected virtual void UpdateListViewItemImage(ListViewItem listViewItem) {
198      T item = listViewItem.Tag as T;
199      int i = listViewItem.ImageIndex;
200      listViewItem.ImageList.Images[i] = item == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : item.ItemImage;
201      listViewItem.ImageIndex = -1;
202      listViewItem.ImageIndex = i;
203    }
204    protected virtual void UpdateListViewItemText(ListViewItem listViewItem) {
205      T item = listViewItem.Tag as T;
206      listViewItem.Text = item == null ? "null" : item.ToString();
207      listViewItem.ToolTipText = item == null ? string.Empty : item.ItemName + ": " + item.ItemDescription;
208    }
209    protected virtual IEnumerable<ListViewItem> GetListViewItemsForItem(T item) {
210      if (item == null) {
211        List<ListViewItem> listViewItems = new List<ListViewItem>();
212        foreach (ListViewItem listViewItem in itemsListView.Items) {
213          if (listViewItem.Tag == null) listViewItems.Add(listViewItem);
214        }
215        return listViewItems;
216      } else {
217        List<ListViewItem> listViewItems = null;
218        itemListViewItemMapping.TryGetValue(item, out listViewItems);
219        return listViewItems == null ? Enumerable.Empty<ListViewItem>() : listViewItems;
220      }
221    }
222
223    #region ListView Events
224    protected virtual void itemsListView_SelectedIndexChanged(object sender, EventArgs e) {
225      addButton.Enabled = itemsListView.SelectedItems.Count > 0 && (Content != null) && !Content.IsReadOnly && !ReadOnly;
226      moveUpButton.Enabled = itemsListView.SelectedItems.Count == 1 &&
227                             itemsListView.SelectedIndices[0] != 0 &&
228                             (Content != null) && !Content.IsReadOnly && !ReadOnly;
229      moveDownButton.Enabled = itemsListView.SelectedItems.Count == 1 &&
230                               itemsListView.SelectedIndices[0] != itemsListView.Items.Count - 1 &&
231                               (Content != null) && !Content.IsReadOnly && !ReadOnly;
232      removeButton.Enabled = itemsListView.SelectedItems.Count > 0 && (Content != null) && !Content.IsReadOnly && !ReadOnly;
233      AdjustListViewColumnSizes();
234
235      if (showDetailsCheckBox.Checked) {
236        if (itemsListView.SelectedItems.Count == 1) {
237          T item = itemsListView.SelectedItems[0].Tag as T;
238          detailsGroupBox.Enabled = true;
239          viewHost.Content = item;
240        } else {
241          viewHost.Content = null;
242          detailsGroupBox.Enabled = false;
243        }
244      }
245    }
246
247    protected virtual void itemsListView_KeyDown(object sender, KeyEventArgs e) {
248      if (e.KeyCode == Keys.Delete) {
249        if ((itemsListView.SelectedItems.Count > 0) && !Content.IsReadOnly && !ReadOnly) {
250          foreach (ListViewItem item in itemsListView.SelectedItems)
251            Content[item.Index] = null;
252        }
253      }
254    }
255
256    protected virtual void itemsListView_DoubleClick(object sender, EventArgs e) {
257      if (itemsListView.SelectedItems.Count == 1) {
258        T item = itemsListView.SelectedItems[0].Tag as T;
259        if (item != null) {
260          IContentView view = MainFormManager.MainForm.ShowContent(item);
261          if (view != null) {
262            view.ReadOnly = ReadOnly;
263            view.Locked = Locked;
264          }
265        }
266      }
267    }
268
269    protected virtual void itemsListView_ItemDrag(object sender, ItemDragEventArgs e) {
270      if (!Locked) {
271        ListViewItem listViewItem = (ListViewItem)e.Item;
272        T item = listViewItem.Tag as T;
273        if (item != null) {
274          DataObject data = new DataObject();
275          data.SetData("Type", item.GetType());
276          data.SetData("Value", item);
277          if (Content.IsReadOnly || ReadOnly) {
278            DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
279          } else {
280            DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
281            if ((result & DragDropEffects.Move) == DragDropEffects.Move)
282              Content[listViewItem.Index] = null;
283          }
284        }
285      }
286    }
287    protected virtual void itemsListView_DragEnterOver(object sender, DragEventArgs e) {
288      e.Effect = DragDropEffects.None;
289      Type type = e.Data.GetData("Type") as Type;
290      if (!Content.IsReadOnly && !ReadOnly && (type != null) && (typeof(T).IsAssignableFrom(type))) {
291        Point p = itemsListView.PointToClient(new Point(e.X, e.Y));
292        ListViewItem listViewItem = itemsListView.GetItemAt(p.X, p.Y);
293        if (listViewItem != null) {
294          if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link;  // ALT key
295          else if ((e.KeyState & 4) == 4) e.Effect = DragDropEffects.Move;  // SHIFT key
296          else if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy;
297          else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) e.Effect = DragDropEffects.Move;
298          else if ((e.AllowedEffect & DragDropEffects.Link) == DragDropEffects.Link) e.Effect = DragDropEffects.Link;
299        }
300      }
301    }
302    protected virtual void itemsListView_DragDrop(object sender, DragEventArgs e) {
303      if (e.Effect != DragDropEffects.None) {
304        T item = e.Data.GetData("Value") as T;
305        if ((e.Effect & DragDropEffects.Copy) == DragDropEffects.Copy) item = (T)item.Clone();
306
307        Point p = itemsListView.PointToClient(new Point(e.X, e.Y));
308        ListViewItem listViewItem = itemsListView.GetItemAt(p.X, p.Y);
309        Content[listViewItem.Index] = item;
310      }
311    }
312    #endregion
313
314    #region Button Events
315    protected virtual void addButton_Click(object sender, EventArgs e) {
316      if (itemsListView.SelectedItems.Count > 0) {
317        T item = CreateItem();
318        if (item != null) {
319          foreach (ListViewItem listViewItem in itemsListView.SelectedItems)
320            Content[listViewItem.Index] = item;
321        }
322      }
323    }
324    protected virtual void moveUpButton_Click(object sender, EventArgs e) {
325      if (itemsListView.SelectedItems.Count == 1) {
326        int index = itemsListView.SelectedIndices[0];
327        T item = Content[index - 1];
328        Content[index - 1] = Content[index];
329        itemsListView.Items[index].Selected = false;
330        itemsListView.Items[index - 1].Selected = true;
331        Content[index] = item;
332      }
333    }
334    protected virtual void moveDownButton_Click(object sender, EventArgs e) {
335      if (itemsListView.SelectedItems.Count == 1) {
336        int index = itemsListView.SelectedIndices[0];
337        T item = Content[index + 1];
338        Content[index + 1] = Content[index];
339        itemsListView.Items[index].Selected = false;
340        itemsListView.Items[index + 1].Selected = true;
341        Content[index] = item;
342      }
343    }
344    protected virtual void removeButton_Click(object sender, EventArgs e) {
345      if (itemsListView.SelectedItems.Count > 0) {
346        foreach (ListViewItem item in itemsListView.SelectedItems)
347          Content[item.Index] = null;
348      }
349    }
350    #endregion
351
352    #region CheckBox Events
353    protected virtual void showDetailsCheckBox_CheckedChanged(object sender, EventArgs e) {
354      if (showDetailsCheckBox.Checked) {
355        splitContainer.Panel2Collapsed = false;
356        detailsGroupBox.Enabled = itemsListView.SelectedItems.Count == 1;
357        viewHost.Content = itemsListView.SelectedItems.Count == 1 ? (T)itemsListView.SelectedItems[0].Tag : null;
358      } else {
359        splitContainer.Panel2Collapsed = true;
360        viewHost.Content = null;
361      }
362    }
363    #endregion
364
365    #region Content Events
366    protected virtual void Content_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
367      if (InvokeRequired)
368        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsReplaced), sender, e);
369      else {
370        int[] selected = new int[itemsListView.SelectedIndices.Count];
371        itemsListView.SelectedIndices.CopyTo(selected, 0);
372
373        List<ListViewItem> listViewItems = new List<ListViewItem>();
374        foreach (IndexedItem<T> item in e.OldItems)
375          listViewItems.Add(itemsListView.Items[item.Index]);
376        foreach (ListViewItem listViewItem in listViewItems)
377          RemoveListViewItem(listViewItem);
378        RebuildImageList();
379
380        foreach (IndexedItem<T> item in e.Items)
381          InsertListViewItem(item.Index, CreateListViewItem(item.Value));
382        AdjustListViewColumnSizes();
383
384        for (int i = 0; i < selected.Length; i++)
385          itemsListView.Items[selected[i]].Selected = true;
386      }
387    }
388    protected virtual void Content_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
389      if (InvokeRequired)
390        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_ItemsMoved), sender, e);
391      else {
392        foreach (IndexedItem<T> item in e.Items) {
393          ListViewItem listViewItem = itemsListView.Items[item.Index];
394          listViewItem.Tag = item.Value;
395          UpdateListViewItemImage(listViewItem);
396          UpdateListViewItemText(listViewItem);
397        }
398      }
399    }
400    protected virtual void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<T>> e) {
401      if (InvokeRequired)
402        Invoke(new CollectionItemsChangedEventHandler<IndexedItem<T>>(Content_CollectionReset), sender, e);
403      else {
404        List<ListViewItem> listViewItems = new List<ListViewItem>();
405        foreach (IndexedItem<T> item in e.OldItems)
406          listViewItems.Add(itemsListView.Items[item.Index]);
407        foreach (ListViewItem listViewItem in listViewItems)
408          RemoveListViewItem(listViewItem);
409        RebuildImageList();
410
411        foreach (IndexedItem<T> item in e.Items)
412          InsertListViewItem(item.Index, CreateListViewItem(item.Value));
413        AdjustListViewColumnSizes();
414      }
415    }
416    #endregion
417
418    #region Item Events
419    protected virtual void Item_ItemImageChanged(object sender, EventArgs e) {
420      if (InvokeRequired)
421        Invoke(new EventHandler(Item_ItemImageChanged), sender, e);
422      else {
423        T item = (T)sender;
424        foreach (ListViewItem listViewItem in GetListViewItemsForItem(item))
425          UpdateListViewItemImage(listViewItem);
426      }
427    }
428    protected virtual void Item_ToStringChanged(object sender, EventArgs e) {
429      if (InvokeRequired)
430        Invoke(new EventHandler(Item_ToStringChanged), sender, e);
431      else {
432        T item = (T)sender;
433        foreach (ListViewItem listViewItem in GetListViewItemsForItem(item))
434          UpdateListViewItemText(listViewItem);
435      }
436    }
437    #endregion
438
439    #region Helpers
440    protected virtual void AdjustListViewColumnSizes() {
441      if (itemsListView.Items.Count > 0) {
442        for (int i = 0; i < itemsListView.Columns.Count; i++)
443          itemsListView.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
444      }
445    }
446    protected virtual void RebuildImageList() {
447      itemsListView.SmallImageList.Images.Clear();
448      foreach (ListViewItem listViewItem in itemsListView.Items) {
449        T item = listViewItem.Tag as T;
450        itemsListView.SmallImageList.Images.Add(item == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : item.ItemImage);
451        listViewItem.ImageIndex = itemsListView.SmallImageList.Images.Count - 1;
452      }
453    }
454    #endregion
455  }
456}
Note: See TracBrowser for help on using the repository browser.