Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 4453 was 4453, checked in by mkommend, 13 years ago

Refactored the Clipboard to handle IExecuteables and repositioned the label in the ViewHost (ticket #1155).

File size: 14.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> 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 could not be saved, because they are locked (e.g. used in a running algorithm). All other items will be saved." +
335          Environment.NewLine + itemNames, "Could not 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.