1 #region License Information
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 * This file is part of HeuristicLab.
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.
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.
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/>.
23 using System
.Collections
;
24 using System
.Collections
.Generic
;
26 using System
.Windows
.Forms
;
27 using HeuristicLab
.Collections
;
28 using HeuristicLab
.Common
;
29 using HeuristicLab
.MainForm
;
30 using HeuristicLab
.MainForm
.WindowsForms
;
31 using HeuristicLab
.PluginInfrastructure
;
33 namespace HeuristicLab
.Core
.Views
{
34 [View("ItemCollection View")]
35 [Content(typeof(ItemCollection
<>), true)]
36 [Content(typeof(IItemCollection
<>), false)]
37 public partial class ItemCollectionView
<T
> : ItemView where T
: class, IItem
{
38 protected Dictionary
<T
, List
<ListViewItem
>> itemListViewItemMapping
;
39 protected TypeSelectorDialog typeSelectorDialog
;
40 protected bool validDragOperation
;
42 public new IItemCollection
<T
> Content
{
43 get { return (IItemCollection<T>)base.Content; }
44 set { base.Content = value; }
47 public ListView ItemsListView
{
48 get { return itemsListView; }
51 public ItemCollectionView() {
52 InitializeComponent();
53 itemListViewItemMapping
= new Dictionary
<T
, List
<ListViewItem
>>();
56 protected override void Dispose(bool disposing
) {
58 if (typeSelectorDialog
!= null) typeSelectorDialog
.Dispose();
59 if (components
!= null) components
.Dispose();
61 base.Dispose(disposing
);
64 protected override void DeregisterContentEvents() {
65 Content
.ItemsAdded
-= new CollectionItemsChangedEventHandler
<T
>(Content_ItemsAdded
);
66 Content
.ItemsRemoved
-= new CollectionItemsChangedEventHandler
<T
>(Content_ItemsRemoved
);
67 Content
.CollectionReset
-= new CollectionItemsChangedEventHandler
<T
>(Content_CollectionReset
);
68 foreach (T item
in itemListViewItemMapping
.Keys
) {
69 DeregisterItemEvents(item
);
71 base.DeregisterContentEvents();
73 protected override void RegisterContentEvents() {
74 base.RegisterContentEvents();
75 Content
.ItemsAdded
+= new CollectionItemsChangedEventHandler
<T
>(Content_ItemsAdded
);
76 Content
.ItemsRemoved
+= new CollectionItemsChangedEventHandler
<T
>(Content_ItemsRemoved
);
77 Content
.CollectionReset
+= new CollectionItemsChangedEventHandler
<T
>(Content_CollectionReset
);
79 protected virtual void DeregisterItemEvents(T item
) {
80 item
.ItemImageChanged
-= new EventHandler(Item_ItemImageChanged
);
81 item
.ToStringChanged
-= new EventHandler(Item_ToStringChanged
);
83 protected virtual void RegisterItemEvents(T item
) {
84 item
.ItemImageChanged
+= new EventHandler(Item_ItemImageChanged
);
85 item
.ToStringChanged
+= new EventHandler(Item_ToStringChanged
);
88 protected override void OnContentChanged() {
89 base.OnContentChanged();
90 itemsListView
.Items
.Clear();
91 itemListViewItemMapping
.Clear();
93 viewHost
.Content
= null;
94 if (Content
!= null) {
95 Caption
+= " (" + Content
.GetType().Name
+ ")";
96 foreach (T item
in Content
)
97 AddListViewItem(CreateListViewItem(item
));
98 AdjustListViewColumnSizes();
99 SortItemsListView(SortOrder
.Ascending
);
103 protected override void SetEnabledStateOfControls() {
104 base.SetEnabledStateOfControls();
105 if (Content
== null) {
106 addButton
.Enabled
= false;
107 sortAscendingButton
.Enabled
= false;
108 sortDescendingButton
.Enabled
= false;
109 removeButton
.Enabled
= false;
110 itemsListView
.Enabled
= false;
111 detailsGroupBox
.Enabled
= false;
113 addButton
.Enabled
= !Content
.IsReadOnly
&& !ReadOnly
;
114 sortAscendingButton
.Enabled
= itemsListView
.Items
.Count
> 1;
115 sortDescendingButton
.Enabled
= itemsListView
.Items
.Count
> 1;
116 removeButton
.Enabled
= !Content
.IsReadOnly
&& !ReadOnly
&& itemsListView
.SelectedItems
.Count
> 0;
117 itemsListView
.Enabled
= true;
118 detailsGroupBox
.Enabled
= itemsListView
.SelectedItems
.Count
== 1;
122 protected virtual T
CreateItem() {
123 if (typeSelectorDialog
== null) {
124 typeSelectorDialog
= new TypeSelectorDialog();
125 typeSelectorDialog
.Caption
= "Select Item";
126 typeSelectorDialog
.TypeSelector
.Caption
= "Available Items";
127 typeSelectorDialog
.TypeSelector
.Configure(typeof(T
), false, true);
130 if (typeSelectorDialog
.ShowDialog(this) == DialogResult
.OK
) {
132 return (T
)typeSelectorDialog
.TypeSelector
.CreateInstanceOfSelectedType();
134 catch (Exception ex
) {
135 ErrorHandling
.ShowErrorDialog(this, ex
);
140 protected virtual ListViewItem
CreateListViewItem(T item
) {
141 ListViewItem listViewItem
= new ListViewItem();
143 listViewItem
.Text
= "null";
144 itemsListView
.SmallImageList
.Images
.Add(HeuristicLab
.Common
.Resources
.VSImageLibrary
.Nothing
);
145 listViewItem
.ImageIndex
= itemsListView
.SmallImageList
.Images
.Count
- 1;
147 listViewItem
.Text
= item
.ToString();
148 listViewItem
.ToolTipText
= item
.ItemName
+ ": " + item
.ItemDescription
;
149 itemsListView
.SmallImageList
.Images
.Add(item
.ItemImage
);
150 listViewItem
.ImageIndex
= itemsListView
.SmallImageList
.Images
.Count
- 1;
151 listViewItem
.Tag
= item
;
155 protected virtual void AddListViewItem(ListViewItem listViewItem
) {
156 if (listViewItem
== null) throw new ArgumentNullException();
157 T item
= (listViewItem
.Tag
as T
);
158 itemsListView
.Items
.Add(listViewItem
);
160 if (!itemListViewItemMapping
.ContainsKey(item
)) {
161 RegisterItemEvents(item
);
162 itemListViewItemMapping
.Add(item
, new List
<ListViewItem
>());
164 itemListViewItemMapping
[item
].Add(listViewItem
);
166 sortAscendingButton
.Enabled
= itemsListView
.Items
.Count
> 1;
167 sortDescendingButton
.Enabled
= itemsListView
.Items
.Count
> 1;
169 protected virtual void RemoveListViewItem(ListViewItem listViewItem
) {
170 if (listViewItem
== null) throw new ArgumentNullException();
171 T item
= (listViewItem
.Tag
as T
);
173 itemListViewItemMapping
[item
].Remove(listViewItem
);
174 if (itemListViewItemMapping
[item
].Count
== 0) {
175 itemListViewItemMapping
.Remove(item
);
176 DeregisterItemEvents(item
);
179 listViewItem
.Remove();
180 sortAscendingButton
.Enabled
= itemsListView
.Items
.Count
> 1;
181 sortDescendingButton
.Enabled
= itemsListView
.Items
.Count
> 1;
183 protected virtual void UpdateListViewItemImage(ListViewItem listViewItem
) {
184 if (listViewItem
== null) throw new ArgumentNullException();
185 T item
= listViewItem
.Tag
as T
;
186 int i
= listViewItem
.ImageIndex
;
187 itemsListView
.SmallImageList
.Images
[i
] = item
== null ? HeuristicLab
.Common
.Resources
.VSImageLibrary
.Nothing
: item
.ItemImage
;
188 listViewItem
.ImageIndex
= -1;
189 listViewItem
.ImageIndex
= i
;
191 protected virtual void UpdateListViewItemText(ListViewItem listViewItem
) {
192 if (listViewItem
== null) throw new ArgumentNullException();
193 T item
= listViewItem
.Tag
as T
;
194 listViewItem
.Text
= item
== null ? "null" : item
.ToString();
195 listViewItem
.ToolTipText
= item
== null ? string.Empty
: item
.ItemName
+ ": " + item
.ItemDescription
;
197 protected virtual IEnumerable
<ListViewItem
> GetListViewItemsForItem(T item
) {
199 List
<ListViewItem
> listViewItems
= new List
<ListViewItem
>();
200 foreach (ListViewItem listViewItem
in itemsListView
.Items
) {
201 if (listViewItem
.Tag
== null) listViewItems
.Add(listViewItem
);
203 return listViewItems
;
205 List
<ListViewItem
> listViewItems
= null;
206 itemListViewItemMapping
.TryGetValue(item
, out listViewItems
);
207 return listViewItems
== null ? Enumerable
.Empty
<ListViewItem
>() : listViewItems
;
211 #region ListView Events
212 protected virtual void itemsListView_SelectedIndexChanged(object sender
, EventArgs e
) {
213 removeButton
.Enabled
= (Content
!= null) && !Content
.IsReadOnly
&& !ReadOnly
&& itemsListView
.SelectedItems
.Count
> 0;
214 AdjustListViewColumnSizes();
215 if (showDetailsCheckBox
.Checked
) {
216 if (itemsListView
.SelectedItems
.Count
== 1) {
217 T item
= (T
)itemsListView
.SelectedItems
[0].Tag
;
218 detailsGroupBox
.Enabled
= true;
219 viewHost
.Content
= item
;
221 viewHost
.Content
= null;
222 detailsGroupBox
.Enabled
= false;
226 protected virtual void itemsListView_KeyDown(object sender
, KeyEventArgs e
) {
227 if (e
.KeyCode
== Keys
.Delete
) {
228 if ((itemsListView
.SelectedItems
.Count
> 0) && !Content
.IsReadOnly
&& !ReadOnly
) {
229 foreach (ListViewItem item
in itemsListView
.SelectedItems
)
230 Content
.Remove((T
)item
.Tag
);
234 protected virtual void itemsListView_DoubleClick(object sender
, EventArgs e
) {
235 if (itemsListView
.SelectedItems
.Count
== 1) {
236 T item
= itemsListView
.SelectedItems
[0].Tag
as T
;
238 IContentView view
= MainFormManager
.MainForm
.ShowContent(item
);
240 view
.ReadOnly
= ReadOnly
;
241 view
.Locked
= Locked
;
246 protected virtual void itemsListView_ItemDrag(object sender
, ItemDragEventArgs e
) {
248 List
<T
> items
= new List
<T
>();
249 foreach (ListViewItem listViewItem
in itemsListView
.SelectedItems
) {
250 T item
= listViewItem
.Tag
as T
;
251 if (item
!= null) items
.Add(item
);
254 if (items
.Count
> 0) {
255 DataObject data
= new DataObject();
256 if (items
.Count
== 1) data
.SetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
, items
[0]);
257 else data
.SetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
, items
);
258 if (Content
.IsReadOnly
|| ReadOnly
) {
259 DoDragDrop(data
, DragDropEffects
.Copy
| DragDropEffects
.Link
);
261 DragDropEffects result
= DoDragDrop(data
, DragDropEffects
.Copy
| DragDropEffects
.Link
| DragDropEffects
.Move
);
262 if ((result
& DragDropEffects
.Move
) == DragDropEffects
.Move
) {
263 foreach (T item
in items
) Content
.Remove(item
);
269 protected virtual void itemsListView_DragEnter(object sender
, DragEventArgs e
) {
270 validDragOperation
= false;
271 if (!Content
.IsReadOnly
&& !ReadOnly
&& (e
.Data
.GetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
) is T
)) {
272 validDragOperation
= true;
273 } else if (!Content
.IsReadOnly
&& !ReadOnly
&& (e
.Data
.GetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
) is IEnumerable
)) {
274 validDragOperation
= true;
275 IEnumerable items
= (IEnumerable
)e
.Data
.GetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
);
276 foreach (object item
in items
)
277 validDragOperation
= validDragOperation
&& (item
is T
);
280 protected virtual void itemsListView_DragOver(object sender
, DragEventArgs e
) {
281 e
.Effect
= DragDropEffects
.None
;
282 if (validDragOperation
) {
283 if ((e
.KeyState
& 32) == 32) e
.Effect
= DragDropEffects
.Link
; // ALT key
284 else if ((e
.KeyState
& 4) == 4) e
.Effect
= DragDropEffects
.Move
; // SHIFT key
285 else if (e
.AllowedEffect
.HasFlag(DragDropEffects
.Copy
)) e
.Effect
= DragDropEffects
.Copy
;
286 else if (e
.AllowedEffect
.HasFlag(DragDropEffects
.Move
)) e
.Effect
= DragDropEffects
.Move
;
287 else if (e
.AllowedEffect
.HasFlag(DragDropEffects
.Link
)) e
.Effect
= DragDropEffects
.Link
;
290 protected virtual void itemsListView_DragDrop(object sender
, DragEventArgs e
) {
291 if (e
.Effect
!= DragDropEffects
.None
) {
292 if (e
.Data
.GetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
) is T
) {
293 T item
= (T
)e
.Data
.GetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
);
294 Content
.Add(e
.Effect
.HasFlag(DragDropEffects
.Copy
) ? (T
)item
.Clone() : item
);
295 } else if (e
.Data
.GetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
) is IEnumerable
) {
296 IEnumerable
<T
> items
= ((IEnumerable
)e
.Data
.GetData(HeuristicLab
.Common
.Constants
.DragDropDataFormat
)).Cast
<T
>();
297 if (e
.Effect
.HasFlag(DragDropEffects
.Copy
)) {
298 Cloner cloner
= new Cloner();
299 items
= items
.Select(x
=> cloner
.Clone(x
));
301 foreach (T item
in items
)
308 #region Button Events
309 protected virtual void addButton_Click(object sender
, EventArgs e
) {
310 T item
= CreateItem();
314 protected virtual void sortAscendingButton_Click(object sender
, EventArgs e
) {
315 SortItemsListView(SortOrder
.Ascending
);
317 protected virtual void sortDescendingButton_Click(object sender
, EventArgs e
) {
318 SortItemsListView(SortOrder
.Descending
);
320 protected virtual void removeButton_Click(object sender
, EventArgs e
) {
321 if (itemsListView
.SelectedItems
.Count
> 0) {
322 foreach (ListViewItem item
in itemsListView
.SelectedItems
)
323 Content
.Remove((T
)item
.Tag
);
324 itemsListView
.SelectedItems
.Clear();
329 #region CheckBox Events
330 protected virtual void showDetailsCheckBox_CheckedChanged(object sender
, EventArgs e
) {
331 if (showDetailsCheckBox
.Checked
) {
332 splitContainer
.Panel2Collapsed
= false;
333 detailsGroupBox
.Enabled
= itemsListView
.SelectedItems
.Count
== 1;
334 viewHost
.Content
= itemsListView
.SelectedItems
.Count
== 1 ? (T
)itemsListView
.SelectedItems
[0].Tag
: null;
336 splitContainer
.Panel2Collapsed
= true;
337 viewHost
.Content
= null;
342 #region Content Events
343 protected virtual void Content_ItemsAdded(object sender
, CollectionItemsChangedEventArgs
<T
> e
) {
345 Invoke(new CollectionItemsChangedEventHandler
<T
>(Content_ItemsAdded
), sender
, e
);
347 foreach (T item
in e
.Items
)
348 AddListViewItem(CreateListViewItem(item
));
349 AdjustListViewColumnSizes();
353 protected virtual void Content_ItemsRemoved(object sender
, CollectionItemsChangedEventArgs
<T
> e
) {
355 Invoke(new CollectionItemsChangedEventHandler
<T
>(Content_ItemsRemoved
), sender
, e
);
357 foreach (T item
in e
.Items
) {
358 //remove only the first matching ListViewItem, because the IItem could be contained multiple times in the ItemCollection
359 ListViewItem listviewItem
= GetListViewItemsForItem(item
).FirstOrDefault();
360 if (listviewItem
!= null) RemoveListViewItem(listviewItem
);
365 protected virtual void Content_CollectionReset(object sender
, CollectionItemsChangedEventArgs
<T
> e
) {
367 Invoke(new CollectionItemsChangedEventHandler
<T
>(Content_CollectionReset
), sender
, e
);
369 foreach (T item
in e
.OldItems
) {
370 //remove only the first matching ListViewItem, because the IItem could be contained multiple times in the ItemCollection
371 ListViewItem listviewItem
= GetListViewItemsForItem(item
).FirstOrDefault();
372 if (listviewItem
!= null) RemoveListViewItem(listviewItem
);
375 foreach (T item
in e
.Items
)
376 AddListViewItem(CreateListViewItem(item
));
382 protected virtual void Item_ItemImageChanged(object sender
, EventArgs e
) {
384 Invoke(new EventHandler(Item_ItemImageChanged
), sender
, e
);
387 foreach (ListViewItem listViewItem
in GetListViewItemsForItem(item
))
388 UpdateListViewItemImage(listViewItem
);
391 protected virtual void Item_ToStringChanged(object sender
, EventArgs e
) {
393 Invoke(new EventHandler(Item_ToStringChanged
), sender
, e
);
396 foreach (ListViewItem listViewItem
in GetListViewItemsForItem(item
))
397 UpdateListViewItemText(listViewItem
);
403 protected virtual void SortItemsListView(SortOrder sortOrder
) {
404 itemsListView
.Sorting
= SortOrder
.None
;
405 itemsListView
.Sorting
= sortOrder
;
406 itemsListView
.Sorting
= SortOrder
.None
;
408 protected virtual void AdjustListViewColumnSizes() {
409 if (itemsListView
.Items
.Count
> 0) {
410 for (int i
= 0; i
< itemsListView
.Columns
.Count
; i
++)
411 itemsListView
.Columns
[i
].AutoResize(ColumnHeaderAutoResizeStyle
.ColumnContent
);
414 protected virtual void RebuildImageList() {
415 itemsListView
.SmallImageList
.Images
.Clear();
416 foreach (ListViewItem listViewItem
in itemsListView
.Items
) {
417 T item
= listViewItem
.Tag
as T
;
418 itemsListView
.SmallImageList
.Images
.Add(item
== null ? HeuristicLab
.Common
.Resources
.VSImageLibrary
.Nothing
: item
.ItemImage
);
419 listViewItem
.ImageIndex
= itemsListView
.SmallImageList
.Images
.Count
- 1;