Free cookie consent management tool by TermsFeed Policy Generator

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

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

Implemented ShowContent method in MainForm which reuses existing views and adapted the ClipBoard (ticket #1372).

File size: 15.1 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 = MainFormManager.MainForm.ShowContent(item, true);
263      }
264    }
265    private void listView_ItemDrag(object sender, ItemDragEventArgs e) {
266      ListViewItem listViewItem = (ListViewItem)e.Item;
267      T item = (T)listViewItem.Tag;
268      DataObject data = new DataObject();
269      data.SetData("Type", item.GetType());
270      data.SetData("Value", item);
271      if (ReadOnly) {
272        DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
273      } else {
274        DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
275        if ((result & DragDropEffects.Move) == DragDropEffects.Move) {
276          RemoveItem(item);
277          RebuildImageList();
278        }
279      }
280    }
281    private void listView_DragEnterOver(object sender, DragEventArgs e) {
282      e.Effect = DragDropEffects.None;
283      Type type = e.Data.GetData("Type") as Type;
284      T item = e.Data.GetData("Value") as T;
285      if (!ReadOnly && (type != null) && (item != null)) {
286        if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link;  // ALT key
287        else if (((e.KeyState & 4) == 4) && !itemListViewItemMapping.ContainsKey(item)) e.Effect = DragDropEffects.Move;  // SHIFT key
288        else if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy;
289        else if (((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) && !itemListViewItemMapping.ContainsKey(item)) e.Effect = DragDropEffects.Move;
290        else if (((e.AllowedEffect & DragDropEffects.Link) == DragDropEffects.Link) && !itemListViewItemMapping.ContainsKey(item)) e.Effect = DragDropEffects.Link;
291      }
292    }
293    private void listView_DragDrop(object sender, DragEventArgs e) {
294      if (e.Effect != DragDropEffects.None) {
295        T item = e.Data.GetData("Value") as T;
296        if ((e.Effect & DragDropEffects.Copy) == DragDropEffects.Copy) item = (T)item.Clone();
297        try {
298          AddItem(item);
299        }
300        catch (Exception ex) {
301          ErrorHandling.ShowErrorDialog(this, ex);
302        }
303      }
304    }
305    #endregion
306
307    #region Button Events
308    private void addButton_Click(object sender, EventArgs e) {
309      if (typeSelectorDialog == null) {
310        typeSelectorDialog = new TypeSelectorDialog();
311        typeSelectorDialog.Caption = "Select Item";
312        typeSelectorDialog.TypeSelector.Caption = "Available Items";
313        typeSelectorDialog.TypeSelector.Configure(typeof(T), false, true);
314      }
315
316      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
317        try {
318          AddItem((T)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType());
319        }
320        catch (Exception ex) {
321          ErrorHandling.ShowErrorDialog(this, ex);
322        }
323      }
324    }
325    private void sortAscendingButton_Click(object sender, EventArgs e) {
326      listView.Sorting = SortOrder.None;
327      listView.Sorting = SortOrder.Ascending;
328    }
329    private void sortDescendingButton_Click(object sender, EventArgs e) {
330      listView.Sorting = SortOrder.None;
331      listView.Sorting = SortOrder.Descending;
332    }
333    private void removeButton_Click(object sender, EventArgs e) {
334      if (listView.SelectedItems.Count > 0) {
335        foreach (ListViewItem item in listView.SelectedItems)
336          RemoveItem((T)item.Tag);
337        RebuildImageList();
338      }
339    }
340    private void saveButton_Click(object sender, EventArgs e) {
341      IEnumerable<T> items = itemListViewItemMapping.Keys.Except(GetStorableItems(itemListViewItemMapping.Keys));
342      if (items.Any()) {
343        string itemNames = string.Join(Environment.NewLine, items.Select(item => item.ToString()).ToArray());
344        MessageBox.Show("The following items are not saved, because they are locked (e.g. used in a running algorithm):" + Environment.NewLine + Environment.NewLine +
345          itemNames + Environment.NewLine + Environment.NewLine + "All other items will be saved.", "Cannot save all items", MessageBoxButtons.OK, MessageBoxIcon.Warning);
346      }
347      Save();
348    }
349    #endregion
350
351    #region Item Events
352    private void Item_ItemImageChanged(object sender, EventArgs e) {
353      if (InvokeRequired)
354        Invoke(new EventHandler(Item_ItemImageChanged), sender, e);
355      else {
356        T item = (T)sender;
357        ListViewItem listViewItem = itemListViewItemMapping[item];
358        int i = listViewItem.ImageIndex;
359        listViewItem.ImageList.Images[i] = item.ItemImage;
360        listViewItem.ImageIndex = -1;
361        listViewItem.ImageIndex = i;
362      }
363    }
364    private void Item_ToStringChanged(object sender, EventArgs e) {
365      if (InvokeRequired)
366        Invoke(new EventHandler(Item_ToStringChanged), sender, e);
367      else {
368        T item = (T)sender;
369        itemListViewItemMapping[item].Text = item.ToString();
370        listView.Sort();
371        AdjustListViewColumnSizes();
372      }
373    }
374    #endregion
375
376    #region Helpers
377    private void AdjustListViewColumnSizes() {
378      if (listView.Items.Count > 0) {
379        for (int i = 0; i < listView.Columns.Count; i++)
380          listView.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
381      }
382    }
383    private void RebuildImageList() {
384      listView.SmallImageList.Images.Clear();
385      foreach (ListViewItem item in listView.Items) {
386        listView.SmallImageList.Images.Add(((T)item.Tag).ItemImage);
387        item.ImageIndex = listView.SmallImageList.Images.Count - 1;
388      }
389    }
390    #endregion
391  }
392}
Note: See TracBrowser for help on using the repository browser.