Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 4500 was 4500, checked in by swagner, 13 years ago

Adapted warning message when not all elements of the clipboard can be saved (#1155)

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