Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core.Views/3.3/Clipboard.cs @ 5264

Last change on this file since 5264 was 5237, checked in by swagner, 14 years ago

#1324:

  • Added performance optimization in all other item collection views
  • Checked and refactored item event registration/deregistration
  • Enabled null items in item collection views
  • Moved non-default Dispose methods from designer files into user files
File size: 15.5 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.IO;
25using System.Linq;
26using System.Threading;
27using System.Windows.Forms;
28using HeuristicLab.MainForm;
29using HeuristicLab.Persistence.Default.Xml;
30using HeuristicLab.PluginInfrastructure;
31
32namespace HeuristicLab.Core.Views {
33  [View("Clipboard")]
34  public sealed partial class Clipboard<T> : HeuristicLab.MainForm.WindowsForms.Sidebar where T : class, IItem {
35    private TypeSelectorDialog typeSelectorDialog;
36    private Dictionary<T, ListViewItem> itemListViewItemMapping;
37
38    private string itemsPath;
39    public string ItemsPath {
40      get { return itemsPath; }
41      private set {
42        if (string.IsNullOrEmpty(value)) throw new ArgumentException(string.Format("Invalid items path \"{0}\".", value));
43        itemsPath = value;
44        try {
45          if (!Directory.Exists(itemsPath)) {
46            Directory.CreateDirectory(itemsPath);
47            // directory creation might take some time -> wait until it is definitively created
48            while (!Directory.Exists(itemsPath)) {
49              Thread.Sleep(100);
50              Directory.CreateDirectory(itemsPath);
51            }
52          }
53        }
54        catch (Exception ex) {
55          throw new ArgumentException(string.Format("Invalid items path \"{0}\".", itemsPath), ex);
56        }
57      }
58    }
59
60    public Clipboard() {
61      InitializeComponent();
62      ItemsPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
63                  Path.DirectorySeparatorChar + "HeuristicLab" + Path.DirectorySeparatorChar + "Clipboard";
64      itemListViewItemMapping = new Dictionary<T, ListViewItem>();
65    }
66    public Clipboard(string itemsPath) {
67      InitializeComponent();
68      ItemsPath = itemsPath;
69      itemListViewItemMapping = new Dictionary<T, ListViewItem>();
70    }
71
72    protected override void Dispose(bool disposing) {
73      if (disposing) {
74        if (typeSelectorDialog != null) typeSelectorDialog.Dispose();
75        foreach (T item in itemListViewItemMapping.Keys) {
76          item.ItemImageChanged -= new EventHandler(Item_ItemImageChanged);
77          item.ToStringChanged -= new EventHandler(Item_ToStringChanged);
78        }
79        if (components != null) components.Dispose();
80      }
81      base.Dispose(disposing);
82    }
83
84    protected override void OnInitialized(EventArgs e) {
85      base.OnInitialized(e);
86      SetEnabledStateOfControls();
87      Enabled = false;
88      infoLabel.Text = "Loading ...";
89      progressBar.Value = 0;
90      infoPanel.Visible = true;
91      ThreadPool.QueueUserWorkItem(new WaitCallback(LoadItems));
92    }
93
94    protected override void SetEnabledStateOfControls() {
95      base.SetEnabledStateOfControls();
96      addButton.Enabled = !ReadOnly;
97      removeButton.Enabled = !ReadOnly && listView.SelectedItems.Count > 0;
98      saveButton.Enabled = !ReadOnly;
99    }
100
101    public void AddItem(T item) {
102      if (InvokeRequired)
103        Invoke(new Action<T>(AddItem), item);
104      else {
105        if (item == null) throw new ArgumentNullException("item", "Cannot add null item to clipboard.");
106        if (!itemListViewItemMapping.ContainsKey(item)) {
107          ListViewItem listViewItem = new ListViewItem(item.ToString());
108          listViewItem.ToolTipText = item.ItemName + ": " + item.ItemDescription;
109          listView.SmallImageList.Images.Add(item.ItemImage);
110          listViewItem.ImageIndex = listView.SmallImageList.Images.Count - 1;
111          listViewItem.Tag = item;
112          listView.Items.Add(listViewItem);
113          itemListViewItemMapping.Add(item, listViewItem);
114          item.ItemImageChanged += new EventHandler(Item_ItemImageChanged);
115          item.ToStringChanged += new EventHandler(Item_ToStringChanged);
116          sortAscendingButton.Enabled = sortDescendingButton.Enabled = listView.Items.Count > 1;
117          AdjustListViewColumnSizes();
118        }
119      }
120    }
121
122    private void RemoveItem(T item) {
123      if (InvokeRequired)
124        Invoke(new Action<T>(RemoveItem), item);
125      else {
126        if (itemListViewItemMapping.ContainsKey(item)) {
127          item.ItemImageChanged -= new EventHandler(Item_ItemImageChanged);
128          item.ToStringChanged -= new EventHandler(Item_ToStringChanged);
129          ListViewItem listViewItem = itemListViewItemMapping[item];
130          listViewItem.Remove();
131          itemListViewItemMapping.Remove(item);
132          sortAscendingButton.Enabled = sortDescendingButton.Enabled = listView.Items.Count > 1;
133        }
134      }
135    }
136    private void Save() {
137      if (InvokeRequired)
138        Invoke(new Action(Save));
139      else {
140        Enabled = false;
141        infoLabel.Text = "Saving ...";
142        progressBar.Value = 0;
143        infoPanel.Visible = true;
144        ThreadPool.QueueUserWorkItem(new WaitCallback(SaveItems));
145      }
146    }
147
148    #region Loading/Saving Items
149    private void LoadItems(object state) {
150      string[] items = Directory.GetFiles(ItemsPath);
151      foreach (string filename in items) {
152        try {
153          T item = XmlParser.Deserialize<T>(filename);
154          OnItemLoaded(item, progressBar.Maximum / items.Length);
155        }
156        catch (Exception) { }
157      }
158      OnAllItemsLoaded();
159    }
160    private void OnItemLoaded(T item, int progress) {
161      if (InvokeRequired)
162        Invoke(new Action<T, int>(OnItemLoaded), item, progress);
163      else {
164        AddItem(item);
165        progressBar.Value += progress;
166      }
167    }
168    private void OnAllItemsLoaded() {
169      if (InvokeRequired)
170        Invoke(new Action(OnAllItemsLoaded));
171      else {
172        Enabled = true;
173        if (listView.Items.Count > 0) {
174          for (int i = 0; i < listView.Columns.Count; i++)
175            listView.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
176        }
177        infoPanel.Visible = false;
178      }
179    }
180    private void SaveItems(object param) {
181      Directory.Delete(ItemsPath, true);
182      Directory.CreateDirectory(ItemsPath);
183      // directory creation might take some time -> wait until it is definitively created
184      while (!Directory.Exists(ItemsPath)) {
185        Thread.Sleep(100);
186        Directory.CreateDirectory(ItemsPath);
187      }
188
189      int i = 0;
190      T[] items = GetStorableItems(itemListViewItemMapping.Keys);
191
192      foreach (T item in items) {
193        try {
194          i++;
195          SetEnabledStateOfContentViews(item, false);
196          XmlGenerator.Serialize(item, ItemsPath + Path.DirectorySeparatorChar + i.ToString("00000000") + ".hl", 9);
197          OnItemSaved(item, progressBar.Maximum / listView.Items.Count);
198        }
199        catch (Exception) { }
200        finally {
201          SetEnabledStateOfContentViews(item, true);
202        }
203      }
204      OnAllItemsSaved();
205    }
206
207    private void OnItemSaved(T item, int progress) {
208      if (item != null) {
209        if (InvokeRequired)
210          Invoke(new Action<T, int>(OnItemSaved), item, progress);
211        else {
212          progressBar.Value += progress;
213        }
214      }
215    }
216    private void OnAllItemsSaved() {
217      if (InvokeRequired)
218        Invoke(new Action(OnAllItemsLoaded));
219      else {
220        Enabled = true;
221        infoPanel.Visible = false;
222      }
223    }
224
225    private void SetEnabledStateOfContentViews(IItem item, bool enabled) {
226      if (InvokeRequired)
227        Invoke((Action<IItem, bool>)SetEnabledStateOfContentViews, item, enabled);
228      else {
229        var views = MainFormManager.MainForm.Views.OfType<IContentView>().Where(v => v.Content == item).ToList();
230        views.ForEach(v => v.Enabled = enabled);
231      }
232    }
233
234    private static T[] GetStorableItems(IEnumerable<T> items) {
235      var query = from item in items
236                  let executeable = item as IExecutable
237                  let views = MainFormManager.MainForm.Views.OfType<IContentView>().Where(v => v.Content == item)
238                  where executeable == null || executeable.ExecutionState != ExecutionState.Started
239                  where !views.Any(v => v.Locked)
240                  select item;
241      T[] itemArray = query.ToArray();
242      return itemArray;
243    }
244    #endregion
245
246    #region ListView Events
247    private void listView_SelectedIndexChanged(object sender, EventArgs e) {
248      removeButton.Enabled = !ReadOnly && listView.SelectedItems.Count > 0;
249    }
250    private void listView_KeyDown(object sender, KeyEventArgs e) {
251      if (e.KeyCode == Keys.Delete) {
252        if (!ReadOnly && (listView.SelectedItems.Count > 0)) {
253          foreach (ListViewItem item in listView.SelectedItems)
254            RemoveItem((T)item.Tag);
255          RebuildImageList();
256        }
257      }
258    }
259    private void listView_DoubleClick(object sender, EventArgs e) {
260      if (listView.SelectedItems.Count == 1) {
261        T item = (T)listView.SelectedItems[0].Tag;
262        IContentView view;
263        view = MainFormManager.MainForm.Views.OfType<IContentView>().Where(x => (x.Content != null) && (x.Content == item)).FirstOrDefault();
264        if (view != null) {
265          view.Show();
266        } else {
267          view = MainFormManager.MainForm.ShowContent(item);
268          if (view != null) {
269            view.ReadOnly = this.ReadOnly;
270          }
271        }
272      }
273    }
274    private void listView_ItemDrag(object sender, ItemDragEventArgs e) {
275      ListViewItem listViewItem = (ListViewItem)e.Item;
276      T item = (T)listViewItem.Tag;
277      DataObject data = new DataObject();
278      data.SetData("Type", item.GetType());
279      data.SetData("Value", item);
280      if (ReadOnly) {
281        DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
282      } else {
283        DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
284        if ((result & DragDropEffects.Move) == DragDropEffects.Move) {
285          RemoveItem(item);
286          RebuildImageList();
287        }
288      }
289    }
290    private void listView_DragEnterOver(object sender, DragEventArgs e) {
291      e.Effect = DragDropEffects.None;
292      Type type = e.Data.GetData("Type") as Type;
293      T item = e.Data.GetData("Value") as T;
294      if (!ReadOnly && (type != null) && (item != null)) {
295        if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link;  // ALT key
296        else if (((e.KeyState & 4) == 4) && !itemListViewItemMapping.ContainsKey(item)) e.Effect = DragDropEffects.Move;  // SHIFT key
297        else if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy;
298        else if (((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) && !itemListViewItemMapping.ContainsKey(item)) e.Effect = DragDropEffects.Move;
299        else if (((e.AllowedEffect & DragDropEffects.Link) == DragDropEffects.Link) && !itemListViewItemMapping.ContainsKey(item)) e.Effect = DragDropEffects.Link;
300      }
301    }
302    private void listView_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        try {
307          AddItem(item);
308        }
309        catch (Exception ex) {
310          ErrorHandling.ShowErrorDialog(this, ex);
311        }
312      }
313    }
314    #endregion
315
316    #region Button Events
317    private void addButton_Click(object sender, EventArgs e) {
318      if (typeSelectorDialog == null) {
319        typeSelectorDialog = new TypeSelectorDialog();
320        typeSelectorDialog.Caption = "Select Item";
321        typeSelectorDialog.TypeSelector.Caption = "Available Items";
322        typeSelectorDialog.TypeSelector.Configure(typeof(T), false, true);
323      }
324
325      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
326        try {
327          AddItem((T)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType());
328        }
329        catch (Exception ex) {
330          ErrorHandling.ShowErrorDialog(this, ex);
331        }
332      }
333    }
334    private void sortAscendingButton_Click(object sender, EventArgs e) {
335      listView.Sorting = SortOrder.None;
336      listView.Sorting = SortOrder.Ascending;
337    }
338    private void sortDescendingButton_Click(object sender, EventArgs e) {
339      listView.Sorting = SortOrder.None;
340      listView.Sorting = SortOrder.Descending;
341    }
342    private void removeButton_Click(object sender, EventArgs e) {
343      if (listView.SelectedItems.Count > 0) {
344        foreach (ListViewItem item in listView.SelectedItems)
345          RemoveItem((T)item.Tag);
346        RebuildImageList();
347      }
348    }
349    private void saveButton_Click(object sender, EventArgs e) {
350      IEnumerable<T> items = itemListViewItemMapping.Keys.Except(GetStorableItems(itemListViewItemMapping.Keys));
351      if (items.Any()) {
352        string itemNames = string.Join(Environment.NewLine, items.Select(item => item.ToString()).ToArray());
353        MessageBox.Show("The following items are not saved, because they are locked (e.g. used in a running algorithm):" + Environment.NewLine + Environment.NewLine +
354          itemNames + Environment.NewLine + Environment.NewLine + "All other items will be saved.", "Cannot save all items", MessageBoxButtons.OK, MessageBoxIcon.Warning);
355      }
356      Save();
357    }
358    #endregion
359
360    #region Item Events
361    private void Item_ItemImageChanged(object sender, EventArgs e) {
362      if (InvokeRequired)
363        Invoke(new EventHandler(Item_ItemImageChanged), sender, e);
364      else {
365        T item = (T)sender;
366        ListViewItem listViewItem = itemListViewItemMapping[item];
367        int i = listViewItem.ImageIndex;
368        listViewItem.ImageList.Images[i] = item.ItemImage;
369        listViewItem.ImageIndex = -1;
370        listViewItem.ImageIndex = i;
371      }
372    }
373    private void Item_ToStringChanged(object sender, EventArgs e) {
374      if (InvokeRequired)
375        Invoke(new EventHandler(Item_ToStringChanged), sender, e);
376      else {
377        T item = (T)sender;
378        itemListViewItemMapping[item].Text = item.ToString();
379        listView.Sort();
380        AdjustListViewColumnSizes();
381      }
382    }
383    #endregion
384
385    #region Helpers
386    private void AdjustListViewColumnSizes() {
387      if (listView.Items.Count > 0) {
388        for (int i = 0; i < listView.Columns.Count; i++)
389          listView.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
390      }
391    }
392    private void RebuildImageList() {
393      listView.SmallImageList.Images.Clear();
394      foreach (ListViewItem item in listView.Items) {
395        listView.SmallImageList.Images.Add(((T)item.Tag).ItemImage);
396        item.ImageIndex = listView.SmallImageList.Images.Count - 1;
397      }
398    }
399    #endregion
400  }
401}
Note: See TracBrowser for help on using the repository browser.