Free cookie consent management tool by TermsFeed Policy Generator

source: branches/histogram/HeuristicLab.Core.Views/3.3/ItemListView.cs @ 6212

Last change on this file since 6212 was 5928, checked in by swagner, 14 years ago

Prevented disappearing of runs in an optimizer when moving the optimizer up or down in an experiment (#1445)

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