Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PersistenceReintegration/HeuristicLab.Core.Views/3.3/Clipboard.cs @ 16351

Last change on this file since 16351 was 14930, checked in by gkronber, 8 years ago

#2520 changed optimizer to use new persistence per default

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