Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core.Views/3.3/ItemCollectionView.cs @ 5371

Last change on this file since 5371 was 5371, checked in by mkommend, 13 years ago

ticket #1324: Added argument null checks in (Add|Insert|Remove|Update)ListViewItem and UpdateListViewItem(Image|Text) methods.

File size: 16.7 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      if (listViewItem == null) throw new ArgumentNullException();
154      T item = (listViewItem.Tag as T);
155      itemsListView.Items.Add(listViewItem);
156      if (item != null) {
157        if (!itemListViewItemMapping.ContainsKey(item)) {
158          RegisterItemEvents(item);
159          itemListViewItemMapping.Add(item, new List<ListViewItem>());
160        }
161        itemListViewItemMapping[item].Add(listViewItem);
162      }
163      sortAscendingButton.Enabled = itemsListView.Items.Count > 1;
164      sortDescendingButton.Enabled = itemsListView.Items.Count > 1;
165    }
166    protected virtual void RemoveListViewItem(ListViewItem listViewItem) {
167      if (listViewItem == null) throw new ArgumentNullException();
168      T item = (listViewItem.Tag as T);
169      if (item != null) {
170        itemListViewItemMapping[item].Remove(listViewItem);
171        if (itemListViewItemMapping[item].Count == 0) {
172          itemListViewItemMapping.Remove(item);
173          DeregisterItemEvents(item);
174        }
175      }
176      listViewItem.Remove();
177      sortAscendingButton.Enabled = itemsListView.Items.Count > 1;
178      sortDescendingButton.Enabled = itemsListView.Items.Count > 1;
179    }
180    protected virtual void UpdateListViewItemImage(ListViewItem listViewItem) {
181      if (listViewItem == null) throw new ArgumentNullException();
182      T item = listViewItem.Tag as T;
183      int i = listViewItem.ImageIndex;
184      listViewItem.ImageList.Images[i] = item == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : item.ItemImage;
185      listViewItem.ImageIndex = -1;
186      listViewItem.ImageIndex = i;
187    }
188    protected virtual void UpdateListViewItemText(ListViewItem listViewItem) {
189      if (listViewItem == null) throw new ArgumentNullException();
190      T item = listViewItem.Tag as T;
191      listViewItem.Text = item == null ? "null" : item.ToString();
192      listViewItem.ToolTipText = item == null ? string.Empty : item.ItemName + ": " + item.ItemDescription;
193    }
194    protected virtual IEnumerable<ListViewItem> GetListViewItemsForItem(T item) {
195      if (item == null) {
196        List<ListViewItem> listViewItems = new List<ListViewItem>();
197        foreach (ListViewItem listViewItem in itemsListView.Items) {
198          if (listViewItem.Tag == null) listViewItems.Add(listViewItem);
199        }
200        return listViewItems;
201      } else {
202        List<ListViewItem> listViewItems = null;
203        itemListViewItemMapping.TryGetValue(item, out listViewItems);
204        return listViewItems == null ? Enumerable.Empty<ListViewItem>() : listViewItems;
205      }
206    }
207
208    #region ListView Events
209    protected virtual void itemsListView_SelectedIndexChanged(object sender, EventArgs e) {
210      removeButton.Enabled = (Content != null) && !Content.IsReadOnly && !ReadOnly && itemsListView.SelectedItems.Count > 0;
211      AdjustListViewColumnSizes();
212      if (showDetailsCheckBox.Checked) {
213        if (itemsListView.SelectedItems.Count == 1) {
214          T item = (T)itemsListView.SelectedItems[0].Tag;
215          detailsGroupBox.Enabled = true;
216          viewHost.Content = item;
217        } else {
218          viewHost.Content = null;
219          detailsGroupBox.Enabled = false;
220        }
221      }
222    }
223    protected virtual void itemsListView_KeyDown(object sender, KeyEventArgs e) {
224      if (e.KeyCode == Keys.Delete) {
225        if ((itemsListView.SelectedItems.Count > 0) && !Content.IsReadOnly && !ReadOnly) {
226          foreach (ListViewItem item in itemsListView.SelectedItems)
227            Content.Remove((T)item.Tag);
228        }
229      }
230    }
231    protected virtual void itemsListView_DoubleClick(object sender, EventArgs e) {
232      if (itemsListView.SelectedItems.Count == 1) {
233        T item = itemsListView.SelectedItems[0].Tag as T;
234        if (item != null) {
235          IContentView view = MainFormManager.MainForm.ShowContent(item);
236          if (view != null) {
237            view.ReadOnly = ReadOnly;
238            view.Locked = Locked;
239          }
240        }
241      }
242    }
243    protected virtual void itemsListView_ItemDrag(object sender, ItemDragEventArgs e) {
244      if (!Locked) {
245        ListViewItem listViewItem = (ListViewItem)e.Item;
246        T item = listViewItem.Tag as T;
247        if (item != null) {
248          DataObject data = new DataObject();
249          data.SetData("Type", item.GetType());
250          data.SetData("Value", item);
251          if (Content.IsReadOnly || ReadOnly) {
252            DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
253          } else {
254            DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
255            if ((result & DragDropEffects.Move) == DragDropEffects.Move)
256              Content.Remove(item);
257          }
258        }
259      }
260    }
261    protected virtual void itemsListView_DragEnterOver(object sender, DragEventArgs e) {
262      e.Effect = DragDropEffects.None;
263      Type type = e.Data.GetData("Type") as Type;
264      if (!Content.IsReadOnly && !ReadOnly && (type != null) && (typeof(T).IsAssignableFrom(type))) {
265        if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link;  // ALT key
266        else if ((e.KeyState & 4) == 4) e.Effect = DragDropEffects.Move;  // SHIFT key
267        else if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy;
268        else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) e.Effect = DragDropEffects.Move;
269        else if ((e.AllowedEffect & DragDropEffects.Link) == DragDropEffects.Link) e.Effect = DragDropEffects.Link;
270      }
271    }
272    protected virtual void itemsListView_DragDrop(object sender, DragEventArgs e) {
273      if (e.Effect != DragDropEffects.None) {
274        T item = e.Data.GetData("Value") as T;
275        if ((e.Effect & DragDropEffects.Copy) == DragDropEffects.Copy) item = (T)item.Clone();
276        Content.Add(item);
277      }
278    }
279    #endregion
280
281    #region Button Events
282    protected virtual void addButton_Click(object sender, EventArgs e) {
283      T item = CreateItem();
284      if (item != null)
285        Content.Add(item);
286    }
287    protected virtual void sortAscendingButton_Click(object sender, EventArgs e) {
288      SortItemsListView(SortOrder.Ascending);
289    }
290    protected virtual void sortDescendingButton_Click(object sender, EventArgs e) {
291      SortItemsListView(SortOrder.Descending);
292    }
293    protected virtual void removeButton_Click(object sender, EventArgs e) {
294      if (itemsListView.SelectedItems.Count > 0) {
295        foreach (ListViewItem item in itemsListView.SelectedItems)
296          Content.Remove((T)item.Tag);
297        itemsListView.SelectedItems.Clear();
298      }
299    }
300    #endregion
301
302    #region CheckBox Events
303    protected virtual void showDetailsCheckBox_CheckedChanged(object sender, EventArgs e) {
304      if (showDetailsCheckBox.Checked) {
305        splitContainer.Panel2Collapsed = false;
306        detailsGroupBox.Enabled = itemsListView.SelectedItems.Count == 1;
307        viewHost.Content = itemsListView.SelectedItems.Count == 1 ? (T)itemsListView.SelectedItems[0].Tag : null;
308      } else {
309        splitContainer.Panel2Collapsed = true;
310        viewHost.Content = null;
311      }
312    }
313    #endregion
314
315    #region Content Events
316    protected virtual void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<T> e) {
317      if (InvokeRequired)
318        Invoke(new CollectionItemsChangedEventHandler<T>(Content_ItemsAdded), sender, e);
319      else {
320        foreach (T item in e.Items)
321          AddListViewItem(CreateListViewItem(item));
322        AdjustListViewColumnSizes();
323      }
324
325    }
326    protected virtual void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<T> e) {
327      if (InvokeRequired)
328        Invoke(new CollectionItemsChangedEventHandler<T>(Content_ItemsRemoved), sender, e);
329      else {
330        foreach (T item in e.Items) {
331          //remove only the first matching ListViewItem, because the IItem could be contained multiple times in the ItemCollection
332          ListViewItem listviewItem = GetListViewItemsForItem(item).FirstOrDefault();
333          if (listviewItem != null) RemoveListViewItem(listviewItem);
334        }
335        RebuildImageList();
336      }
337    }
338    protected virtual void Content_CollectionReset(object sender, CollectionItemsChangedEventArgs<T> e) {
339      if (InvokeRequired)
340        Invoke(new CollectionItemsChangedEventHandler<T>(Content_CollectionReset), sender, e);
341      else {
342        foreach (T item in e.OldItems) {
343          //remove only the first matching ListViewItem, because the IItem could be contained multiple times in the ItemCollection
344          ListViewItem listviewItem = GetListViewItemsForItem(item).FirstOrDefault();
345          if (listviewItem != null) RemoveListViewItem(listviewItem);
346        }
347        RebuildImageList();
348        foreach (T item in e.Items)
349          AddListViewItem(CreateListViewItem(item));
350      }
351    }
352    #endregion
353
354    #region Item Events
355    protected virtual void Item_ItemImageChanged(object sender, EventArgs e) {
356      if (InvokeRequired)
357        Invoke(new EventHandler(Item_ItemImageChanged), sender, e);
358      else {
359        T item = (T)sender;
360        foreach (ListViewItem listViewItem in GetListViewItemsForItem(item))
361          UpdateListViewItemImage(listViewItem);
362      }
363    }
364    protected virtual void Item_ToStringChanged(object sender, EventArgs e) {
365      if (InvokeRequired)
366        Invoke(new EventHandler(Item_ToStringChanged), sender, e);
367      else {
368        T item = (T)sender;
369        foreach (ListViewItem listViewItem in GetListViewItemsForItem(item))
370          UpdateListViewItemText(listViewItem);
371      }
372    }
373    #endregion
374
375    #region Helpers
376    protected virtual void SortItemsListView(SortOrder sortOrder) {
377      itemsListView.Sorting = SortOrder.None;
378      itemsListView.Sorting = sortOrder;
379      itemsListView.Sorting = SortOrder.None;
380    }
381    protected virtual void AdjustListViewColumnSizes() {
382      if (itemsListView.Items.Count > 0) {
383        for (int i = 0; i < itemsListView.Columns.Count; i++)
384          itemsListView.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
385      }
386    }
387    protected virtual void RebuildImageList() {
388      itemsListView.SmallImageList.Images.Clear();
389      foreach (ListViewItem listViewItem in itemsListView.Items) {
390        T item = listViewItem.Tag as T;
391        itemsListView.SmallImageList.Images.Add(item == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : item.ItemImage);
392        listViewItem.ImageIndex = itemsListView.SmallImageList.Images.Count - 1;
393      }
394    }
395    #endregion
396  }
397}
Note: See TracBrowser for help on using the repository browser.