Free cookie consent management tool by TermsFeed Policy Generator

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