Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Optimization.Views/3.3/ExperimentTreeView.cs @ 6539

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

#1555: Optimized rebuilding of the image list due to performance reasons.

File size: 38.1 KB
RevLine 
[6471]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.Drawing;
26using System.Linq;
27using System.Windows.Forms;
28using HeuristicLab.Collections;
29using HeuristicLab.Common;
[6524]30using HeuristicLab.Core;
[6471]31using HeuristicLab.Core.Views;
[6496]32using HeuristicLab.MainForm;
[6471]33using HeuristicLab.PluginInfrastructure;
34
35namespace HeuristicLab.Optimization.Views {
36  public sealed partial class ExperimentTreeView : ItemView {
37    private TypeSelectorDialog typeSelectorDialog;
[6524]38    private Dictionary<INamedItem, List<TreeNode>> treeNodeTagMapping;
[6471]39
40    public ExperimentTreeView() {
41      InitializeComponent();
[6524]42      treeNodeTagMapping = new Dictionary<INamedItem, List<TreeNode>>();
[6471]43    }
44
45    protected override void Dispose(bool disposing) {
46      if (disposing) {
47        if (typeSelectorDialog != null) typeSelectorDialog.Dispose();
48        if (components != null) components.Dispose();
49      }
50      base.Dispose(disposing);
51    }
52
[6488]53    #region necessary code to handle dock correctly regarding the expanded nodes
54    bool[] expandendedState;
55    protected override void OnHandleCreated(EventArgs e) {
56      base.OnHandleCreated(e);
57      if (expandendedState == null) return;
58      var nodes = IterateTreeNodes().ToList();
59      for (int i = 0; i < nodes.Count; i++)
60        if (expandendedState[i]) nodes[i].Expand();
61    }
62    protected override void OnHandleDestroyed(EventArgs e) {
63      base.OnHandleDestroyed(e);
64      var nodes = IterateTreeNodes().ToList();
65      expandendedState = new bool[nodes.Count];
66      for (int i = 0; i < nodes.Count; i++)
67        expandendedState[i] = nodes[i].IsExpanded;
68    }
69    #endregion
70
[6471]71    public new Experiment Content {
72      get { return (Experiment)base.Content; }
73      set { base.Content = value; }
74    }
75
76    #region events registration
77    protected override void RegisterContentEvents() {
78      base.RegisterContentEvents();
79      Content.ExecutionStateChanged += new EventHandler(Content_ExecutionStateChanged);
80      Content.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
81      Content.Optimizers.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsMoved);
82      Content.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
83      Content.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
84      Content.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
85    }
86
87    protected override void DeregisterContentEvents() {
88      Content.ExecutionStateChanged -= new EventHandler(Content_ExecutionStateChanged);
89      Content.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
90      Content.Optimizers.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsMoved);
91      Content.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
92      Content.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
93      Content.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
[6524]94      foreach (var optimizer in treeNodeTagMapping.Keys)
95        DeregisterNamedItemEvents(optimizer);
[6471]96      base.DeregisterContentEvents();
97    }
98
[6524]99    private void RegisterNamedItemEvents(INamedItem namedItem) {
100      namedItem.ToStringChanged += new EventHandler(namedItem_ToStringChanged);
101      namedItem.ItemImageChanged += new EventHandler(namedItem_ItemImageChanged);
[6471]102
[6524]103      var algorithm = namedItem as IAlgorithm;
104      var batchRun = namedItem as BatchRun;
105      var experiment = namedItem as Experiment;
106
107      if (algorithm != null) {
108        algorithm.ProblemChanged += new EventHandler(algorithm_ProblemChanged);
109      } else if (batchRun != null) {
[6471]110        batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged);
[6524]111      } else if (experiment != null) {
[6471]112        experiment.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
113        experiment.Optimizers.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsMoved);
114        experiment.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
115        experiment.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
116        experiment.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
117      }
118    }
119
[6524]120    private void DeregisterNamedItemEvents(INamedItem namedItem) {
121      namedItem.ToStringChanged -= new EventHandler(namedItem_ToStringChanged);
122      namedItem.ItemImageChanged -= new EventHandler(namedItem_ItemImageChanged);
123
124      var algorithm = namedItem as IAlgorithm;
125      var batchRun = namedItem as BatchRun;
126      var experiment = namedItem as Experiment;
127      if (algorithm != null) {
128        algorithm.ProblemChanged -= new EventHandler(algorithm_ProblemChanged);
129      } else if (batchRun != null) {
[6471]130        batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged);
[6524]131      } else if (experiment != null) {
[6471]132        experiment.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
133        experiment.Optimizers.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsMoved);
134        experiment.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
135        experiment.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
136        experiment.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
137      }
138    }
139    #endregion
140
141    protected override void OnContentChanged() {
142      base.OnContentChanged();
143      if (Content == null) {
[6524]144        treeView.Nodes.Clear();
[6471]145      } else {
146        UpdateOptimizerTreeView();
[6524]147        treeView.ExpandAll();
[6471]148      }
149    }
150
151    #region content events
152    private void Content_ExecutionStateChanged(object sender, EventArgs e) {
153      if (InvokeRequired) {
154        Invoke((Action<object, EventArgs>)Content_ExecutionStateChanged, sender, e);
155        return;
156      }
157      SetEnabledStateOfControls();
158    }
159
[6524]160    private void algorithm_ProblemChanged(object sender, EventArgs e) {
[6471]161      if (InvokeRequired) {
[6524]162        Invoke((Action<object, EventArgs>)algorithm_ProblemChanged, sender, e);
[6471]163        return;
164      }
[6524]165
166      var algorithm = (IAlgorithm)sender;
167      foreach (TreeNode node in treeNodeTagMapping[algorithm]) {
168        foreach (TreeNode childNode in node.Nodes.OfType<TreeNode>().ToList()) {
169          DisposeTreeNode(childNode);
170          childNode.Remove();
171        }
172        foreach (TreeNode childNode in CreateAlgorithmChildNodes(algorithm))
173          node.Nodes.Add(childNode);
174        node.Expand();
175      }
176
[6471]177      RebuildImageList();
[6524]178      UpdateDetailsViewHost();
[6471]179    }
180
181    private void batchRun_OptimizerChanged(object sender, EventArgs e) {
182      if (InvokeRequired) {
183        Invoke((Action<object, EventArgs>)batchRun_OptimizerChanged, sender, e);
184        return;
185      }
186      var batchRun = (BatchRun)sender;
[6524]187      foreach (TreeNode node in treeNodeTagMapping[batchRun]) {
188        foreach (TreeNode childNode in node.Nodes.OfType<TreeNode>().ToList()) {
[6471]189          DisposeTreeNode(childNode);
190          childNode.Remove();
191        }
192
193        if (batchRun.Optimizer != null) {
[6524]194          UpdateChildTreeNodes(node.Nodes, batchRun);
[6471]195          node.Expand();
196        }
197      }
198      RebuildImageList();
[6485]199      UpdateDetailsViewHost();
[6471]200    }
201
202    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
203      if (InvokeRequired) {
204        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_ItemsAdded, sender, e);
205        return;
206      }
207
208      var optimizerList = (OptimizerList)sender;
209      IEnumerable<TreeNodeCollection> parentNodes;
[6524]210      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
[6471]211      else {
[6524]212        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
213        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
[6471]214      }
215
216      foreach (TreeNodeCollection parentNode in parentNodes) {
217        foreach (var childOptimizer in e.Items) {
218          TreeNode childNode = CreateTreeNode(childOptimizer.Value);
219          UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value);
220          parentNode.Insert(childOptimizer.Index, childNode);
221          childNode.ExpandAll();
222          if (childNode.Parent != null) childNode.Parent.ExpandAll();
223        }
224      }
225      RebuildImageList();
226    }
227    private void Optimizers_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
228      if (InvokeRequired) {
229        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_ItemsMoved, sender, e);
230        return;
231      }
232
233      var optimizerList = (OptimizerList)sender;
234      IEnumerable<TreeNodeCollection> parentNodes;
[6524]235      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
[6471]236      else {
[6524]237        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
238        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
[6471]239      }
240
241      foreach (TreeNodeCollection parentNode in parentNodes) {
242        //get all effected child nodes
243        foreach (TreeNode childNode in parentNode.OfType<TreeNode>()
244          .Where(n => e.OldItems.Select(x => x.Value).Contains((IOptimizer)n.Tag)).ToList()) {
245          DisposeTreeNode(childNode);
246          childNode.Remove();
247        }
248
249        foreach (var childOptimizer in e.Items) {
250          TreeNode childNode = CreateTreeNode(childOptimizer.Value);
251          UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value);
252          childNode.ExpandAll();
253          parentNode.Insert(childOptimizer.Index, childNode);
254        }
255      }
256      RebuildImageList();
[6485]257      UpdateDetailsViewHost();
[6471]258    }
259    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
260      if (InvokeRequired) {
261        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_ItemsRemoved, sender, e);
262        return;
263      }
264
265      var optimizerList = (OptimizerList)sender;
266      IEnumerable<TreeNodeCollection> parentNodes;
[6524]267      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
[6471]268      else {
[6524]269        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
270        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
[6471]271      }
272
273      foreach (TreeNodeCollection parentNode in parentNodes) {
274        foreach (var childOptimizer in e.Items) {
275          TreeNode childNode = parentNode[childOptimizer.Index];
276          DisposeTreeNode(childNode);
277          childNode.Remove();
278        }
279      }
280      RebuildImageList();
[6485]281      UpdateDetailsViewHost();
[6471]282    }
283    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
284      if (InvokeRequired) {
285        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_ItemsReplaced, sender, e);
286        return;
287      }
288
289      var optimizerList = (OptimizerList)sender;
290      IEnumerable<TreeNodeCollection> parentNodes;
[6524]291      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
[6471]292      else {
[6524]293        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
294        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
[6471]295      }
296
297      foreach (TreeNodeCollection parentNode in parentNodes) {
298        foreach (var childOptimizer in e.OldItems) {
299          TreeNode childNode = parentNode.Cast<TreeNode>().Where(n => n.Tag == childOptimizer.Value && n.Index == childOptimizer.Index).First();
300          DisposeTreeNode(childNode);
301          childNode.Remove();
302        }
303        foreach (var childOptimizer in e.Items) {
304          TreeNode childNode = CreateTreeNode(childOptimizer.Value);
305          UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value);
306          parentNode.Insert(childOptimizer.Index, childNode);
307        }
308      }
309      RebuildImageList();
[6485]310      UpdateDetailsViewHost();
[6471]311    }
312    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
313      if (InvokeRequired) {
314        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_CollectionReset, sender, e);
315        return;
316      }
317
318      var optimizerList = (OptimizerList)sender;
319      IEnumerable<TreeNodeCollection> parentNodes;
[6524]320      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
[6471]321      else {
[6524]322        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
323        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
[6471]324      }
325
326      foreach (TreeNodeCollection parentNode in parentNodes) {
327        foreach (var childOptimizer in e.OldItems) {
328          TreeNode childNode = parentNode.Cast<TreeNode>().Where(n => n.Tag == childOptimizer.Value && n.Index == childOptimizer.Index).First();
329          DisposeTreeNode(childNode);
330          childNode.Remove();
331        }
332        foreach (var childOptimizer in e.Items) {
333          TreeNode childNode = CreateTreeNode(childOptimizer.Value);
334          UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value);
335          parentNode.Insert(childOptimizer.Index, childNode);
336        }
337      }
338      RebuildImageList();
[6485]339      UpdateDetailsViewHost();
[6471]340    }
341
[6524]342    private void namedItem_ToStringChanged(object sender, EventArgs e) {
[6471]343      if (InvokeRequired) {
[6524]344        Invoke((Action<object, EventArgs>)namedItem_ToStringChanged, sender, e);
[6471]345        return;
346      }
[6524]347      var namedItem = (INamedItem)sender;
348      foreach (TreeNode node in treeNodeTagMapping[namedItem])
349        node.Text = namedItem.ToString();
[6471]350    }
[6524]351
352    private void namedItem_ItemImageChanged(object sender, EventArgs e) {
353      if (InvokeRequired) {
354        Invoke((Action<object, EventArgs>)namedItem_ItemImageChanged, sender, e);
355        return;
356      }
357      INamedItem namedItem = (INamedItem)sender;
358      foreach (TreeNode node in treeNodeTagMapping[namedItem]) {
359        treeView.ImageList.Images[node.ImageIndex] = namedItem.ItemImage;
360        node.ImageIndex = node.ImageIndex;
361      }
362      SetEnabledStateOfControls();
363    }
[6471]364    #endregion
365
[6524]366    protected override void PropagateStateChanges(Control control, Type type, System.Reflection.PropertyInfo propertyInfo) {
367      return;
368    }
369
[6471]370    protected override void SetEnabledStateOfControls() {
371      base.SetEnabledStateOfControls();
[6524]372      IOptimizer optimizer = null;
373      IAlgorithm algorithm = null;
[6471]374      BatchRun batchRun = null;
375      Experiment experiment = null;
[6524]376
377      IOptimizer parentOptimizer = null;
378      Experiment parentExperiment = null;
379
380      if (treeView.SelectedNode != null) {
381        optimizer = treeView.SelectedNode.Tag as IOptimizer;
382        algorithm = optimizer as IAlgorithm;
383        batchRun = optimizer as BatchRun;
384        experiment = optimizer as Experiment;
385
386        if (treeView.SelectedNode.Parent != null) parentOptimizer = treeView.SelectedNode.Parent.Tag as IOptimizer;
387        else parentOptimizer = Content;
388
389        parentExperiment = parentOptimizer as Experiment;
[6471]390      }
391
[6524]392      treeView.Enabled = Content != null;
393      if (parentOptimizer != null) {
394        detailsViewHost.ReadOnly = parentOptimizer.ExecutionState == ExecutionState.Started;
395        detailsViewHost.Locked = parentOptimizer.ExecutionState == ExecutionState.Started;
396      }
[6471]397
398      addButton.Enabled = Content != null && !Locked && !ReadOnly &&
[6531]399        (treeView.SelectedNode == null || experiment != null || batchRun != null || algorithm != null);
[6471]400      moveUpButton.Enabled = Content != null && !Locked && !ReadOnly &&
[6524]401        treeView.SelectedNode != null && treeView.SelectedNode.PrevNode != null && parentExperiment != null;
[6471]402      moveDownButton.Enabled = Content != null && !Locked && !ReadOnly &&
[6524]403        treeView.SelectedNode != null && treeView.SelectedNode.NextNode != null && parentExperiment != null;
404      removeButton.Enabled = Content != null && !Locked && !ReadOnly && optimizer != null;
[6471]405    }
406
407    private void UpdateOptimizerTreeView() {
[6524]408      treeView.Nodes.Clear();
409      UpdateChildTreeNodes(treeView.Nodes, Content);
[6471]410      RebuildImageList();
411    }
412
413    private void UpdateChildTreeNodes(TreeNodeCollection collection, IOptimizer optimizer) {
414      var batchRun = optimizer as BatchRun;
415      var experiment = optimizer as Experiment;
[6524]416
417      if (batchRun != null && batchRun.Optimizer != null) UpdateChildTreeNodes(collection, new List<IOptimizer>() { batchRun.Optimizer });
418      else if (experiment != null) UpdateChildTreeNodes(collection, experiment.Optimizers);
[6471]419    }
420    private void UpdateChildTreeNodes(TreeNodeCollection collection, IEnumerable<IOptimizer> optimizers) {
421      foreach (IOptimizer optimizer in optimizers) {
422        var node = CreateTreeNode(optimizer);
423        collection.Add(node);
424        UpdateChildTreeNodes(node.Nodes, optimizer);
425      }
426    }
427
428
429    #region drag & drop
430    private void optimizerTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
431      if (Locked) return;
432
433      TreeNode selectedNode = (TreeNode)e.Item;
[6524]434      var item = (IItem)selectedNode.Tag;
[6529]435      if (item == null) return;
436
[6471]437      DataObject data = new DataObject();
[6524]438      data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, item);
[6471]439      validDragOperation = true;
440
[6524]441      if (ReadOnly || !(item is IOptimizer)) {
[6471]442        DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
443      } else {
444        DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
445        if ((result & DragDropEffects.Move) == DragDropEffects.Move) {
[6524]446          var optimizer = (IOptimizer)item;
[6471]447          if (selectedNode.Parent == null) Content.Optimizers.Remove(optimizer);
448          else {
449            var parentOptimizer = (IOptimizer)selectedNode.Parent.Tag;
450            var parentBatchRun = parentOptimizer as BatchRun;
451            var parentExperiment = parentOptimizer as Experiment;
452            if (parentBatchRun != null) parentBatchRun.Optimizer = null;
453            else if (parentExperiment != null) parentExperiment.Optimizers.Remove(optimizer);
454            else throw new NotSupportedException("Handling for specific type not implemented" + parentOptimizer.GetType());
455          }
456        }
457      }
458    }
459
460    private bool validDragOperation = false;
461    private void optimizerTreeView_DragEnter(object sender, DragEventArgs e) {
462      validDragOperation = false;
463      if (!ReadOnly) {
[6529]464        var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
465        if (data is IOptimizer) validDragOperation = true;
466        else if (data is IProblem) validDragOperation = true;
467        else if (data is IEnumerable) {
468          IEnumerable items = (IEnumerable)data;
[6471]469          validDragOperation = true;
470          foreach (object item in items)
471            validDragOperation = validDragOperation && (item is IOptimizer);
472        }
473      }
474    }
475    private void optimizerTreeView_DragOver(object sender, DragEventArgs e) {
476      e.Effect = DragDropEffects.None;
[6529]477      if (!validDragOperation) return;
478      Point coordinates = treeView.PointToClient(new Point(e.X, e.Y));
479      TreeNode node = treeView.GetNodeAt(coordinates);
480      Experiment experiment = null;
481      BatchRun batchRun = null;
482      Algorithm algorithm = null;
[6471]483
[6529]484      if (node == null) experiment = Content;
485      else {
486        experiment = node.Tag as Experiment;
487        batchRun = node.Tag as BatchRun;
488        algorithm = node.Tag as Algorithm;
489      }
[6471]490
[6529]491      if (batchRun == null && experiment == null && algorithm == null) return;
[6471]492
[6529]493      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
[6471]494
[6529]495      if (algorithm != null) {
496        var problem = data as IProblem;
497        if (problem == null) return;
498        if (!algorithm.ProblemType.IsAssignableFrom(problem.GetType())) return;
499      } else if (batchRun != null) {
500        var optimizer = data as IOptimizer;
501        if (optimizer == null) return;
502        if (batchRun == optimizer) return;
503        if (optimizer.NestedOptimizers.Contains(batchRun)) return;
504      } //do not allow recursive nesting of contents
505      else if (experiment != null) {
506        var optimizer = data as IOptimizer;
507        IEnumerable<IOptimizer> optimizers = null;
508        var enumerable = data as IEnumerable;
509        if (enumerable != null) optimizers = enumerable.Cast<IOptimizer>();
510        if (experiment == optimizer) return;
511        if (optimizer != null && optimizer.NestedOptimizers.Contains(experiment)) return;
512        if (optimizers != null && optimizers.Any(x => x.NestedOptimizers.Contains(experiment))) return;
513      }
[6471]514
[6529]515      if ((e.KeyState & 32) == 32 && e.AllowedEffect.HasFlag(DragDropEffects.Link)) e.Effect = DragDropEffects.Link;  // ALT key
516      else if ((e.KeyState & 4) == 4 && e.AllowedEffect.HasFlag(DragDropEffects.Move)) e.Effect = DragDropEffects.Move;  // SHIFT key
517      else if (e.AllowedEffect.HasFlag(DragDropEffects.Copy)) e.Effect = DragDropEffects.Copy;
518      else if (e.AllowedEffect.HasFlag(DragDropEffects.Move)) e.Effect = DragDropEffects.Move;
519      else if (e.AllowedEffect.HasFlag(DragDropEffects.Link)) e.Effect = DragDropEffects.Link;
[6471]520    }
[6529]521
[6471]522    private void optimizerTreeView_DragDrop(object sender, DragEventArgs e) {
[6524]523      Point coordinates = treeView.PointToClient(new Point(e.X, e.Y));
524      TreeNode node = treeView.GetNodeAt(coordinates);
[6529]525      Algorithm algorithm = null;
526      BatchRun batchRun = null;
[6471]527      Experiment experiment = null;
528
529      if (node == null) experiment = Content;
530      else {
[6529]531        algorithm = node.Tag as Algorithm;
532        batchRun = node.Tag as BatchRun;
[6471]533        experiment = node.Tag as Experiment;
534      }
535
[6529]536      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
537      if (data is IProblem) {
538        var problem = (IProblem)data;
539        if (e.Effect.HasFlag(DragDropEffects.Copy)) problem = (IProblem)problem.Clone();
540        algorithm.Problem = problem;
541      } else if (data is IOptimizer) {
542        IOptimizer optimizer = (IOptimizer)data;
[6471]543        if (e.Effect.HasFlag(DragDropEffects.Copy)) optimizer = (IOptimizer)optimizer.Clone();
544        if (batchRun != null) batchRun.Optimizer = optimizer;
545        else if (experiment != null) experiment.Optimizers.Add(optimizer);
546        else throw new NotSupportedException("Handling for specific type not implemented" + node.Tag.GetType());
[6529]547      } else if (data is IEnumerable) {
548        IEnumerable<IOptimizer> optimizers = ((IEnumerable)data).Cast<IOptimizer>();
[6471]549        if (e.Effect.HasFlag(DragDropEffects.Copy)) {
550          Cloner cloner = new Cloner();
[6529]551          optimizers = optimizers.Select(o => cloner.Clone(o));
[6471]552        }
553        if (experiment != null) experiment.Optimizers.AddRange(optimizers);
554        else throw new NotSupportedException("Handling for specific type not implemented" + node.Tag.GetType());
555      }
556    }
557    #endregion
558
559    #region control events
[6496]560    private void optimizerTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
[6517]561      if (rightClickOccured) return;
[6496]562      if (e.X < e.Node.Bounds.Left || e.X > e.Node.Bounds.Right) return;
[6517]563      e.Node.Toggle();
[6524]564      IContent optimizer = (IContent)e.Node.Tag;
[6496]565      MainFormManager.MainForm.ShowContent(optimizer);
[6471]566    }
[6496]567    private void optimizerTreeview_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) {
568      if (e.X < e.Node.Bounds.Left || e.X > e.Node.Bounds.Right) return;
[6524]569      treeView.SelectedNode = e.Node;
570      detailsViewHost.Content = (IContent)e.Node.Tag;
[6496]571      SetEnabledStateOfControls();
572    }
[6471]573    private void optimizerTreeView_MouseDown(object sender, MouseEventArgs e) {
574      // enables deselection of treeNodes
[6517]575      if (e.Button != MouseButtons.Right) rightClickOccured = false;
[6524]576      if (treeView.SelectedNode == null) return;
[6471]577      Point coordinates = new Point(e.X, e.Y);
[6524]578      TreeNode node = treeView.GetNodeAt(coordinates);
[6496]579      if (node == null || coordinates.X < node.Bounds.Left || coordinates.X > node.Bounds.Right) {
[6524]580        treeView.SelectedNode = null;
[6471]581        detailsViewHost.Content = null;
582        SetEnabledStateOfControls();
583      }
584    }
585
[6517]586
[6485]587    private void optimizerTreeView_KeyDown(object sender, KeyEventArgs e) {
588      if (ReadOnly) return;
589      if (e.KeyCode != Keys.Delete) return;
[6524]590      if (treeView.SelectedNode == null) return;
591      if (!(treeView.SelectedNode.Tag is IOptimizer)) return;
[6485]592
[6524]593      var treeNode = treeView.SelectedNode;
[6485]594      var optimizer = (IOptimizer)treeNode.Tag;
595
596      if (treeNode.Parent == null)
597        Content.Optimizers.Remove(optimizer);
598      else {
599        var batchRun = treeNode.Parent.Tag as BatchRun;
600        var experiment = treeNode.Parent.Tag as Experiment;
601        if (batchRun != null) batchRun.Optimizer = null;
602        else if (experiment != null) experiment.Optimizers.Remove(optimizer);
[6524]603        else throw new NotSupportedException("Handling for specific type not implemented" + treeView.SelectedNode.Tag.GetType());
[6485]604      }
605      SetEnabledStateOfControls();
606      UpdateDetailsViewHost();
607      RebuildImageList();
608    }
609
[6517]610    private bool rightClickOccured = true;
611    private TreeNode toolStripMenuNode = null;
612    private void optimizerTreeView_RightClick(object sender, EventArgs e) {
613      rightClickOccured = true;
[6524]614      Point coordinates = treeView.PointToClient(Cursor.Position);
615      toolStripMenuNode = treeView.GetNodeAt(coordinates);
[6517]616
617      if (toolStripMenuNode != null && coordinates.X >= toolStripMenuNode.Bounds.Left && coordinates.X <= toolStripMenuNode.Bounds.Right) {
[6524]618        treeView.SelectedNode = toolStripMenuNode;
[6517]619        detailsViewHost.Content = (IContent)toolStripMenuNode.Tag;
620        SetEnabledStateOfControls();
621
622        ExpandToolStripMenuItem.Enabled = !toolStripMenuNode.IsExpanded && toolStripMenuNode.Nodes.Count > 0;
623        ExpandToolStripMenuItem.Visible = !toolStripMenuNode.IsExpanded && toolStripMenuNode.Nodes.Count > 0;
624        CollapseToolStripMenuItem.Enabled = toolStripMenuNode.IsExpanded;
625        CollapseToolStripMenuItem.Visible = toolStripMenuNode.IsExpanded;
[6526]626        EditNodeLabelToolStripMenuItem.Enabled = toolStripMenuNode.Tag != null && toolStripMenuNode.Tag is INamedItem;
627        EditNodeLabelToolStripMenuItem.Visible = toolStripMenuNode.Tag != null && toolStripMenuNode.Tag is INamedItem;
[6517]628        if (contextMenuStrip.Items.Cast<ToolStripMenuItem>().Any(item => item.Enabled))
629          contextMenuStrip.Show(Cursor.Position);
630      }
631    }
632
633    private void ExpandToolStripMenuItem_Click(object sender, EventArgs e) {
634      if (toolStripMenuNode != null) toolStripMenuNode.ExpandAll();
635    }
636    private void CollapseToolStripMenuItem_Click(object sender, EventArgs e) {
637      if (toolStripMenuNode != null) toolStripMenuNode.Collapse();
638    }
[6526]639    private void EditNodeLabelToolStripMenuItem_Click(object sender, EventArgs e) {
640      if (toolStripMenuNode != null) {
641        if (!toolStripMenuNode.IsEditing) toolStripMenuNode.BeginEdit();
642      }
643    }
[6517]644
[6526]645
646    private void treeView_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e) {
[6531]647      if (Locked) e.CancelEdit = true;
648      if (ReadOnly) e.CancelEdit = true;
649      if (e.Node.Tag == null) e.CancelEdit = true;
650      if (!(e.Node.Tag is NamedItem)) e.CancelEdit = true;
[6526]651    }
652    private void treeView_AfterLabelEdit(object sender, NodeLabelEditEventArgs e) {
653      if (e.Label == null) return;
654
655      e.Node.EndEdit(false);
656      var namedItem = (INamedItem)e.Node.Tag;
657      namedItem.Name = e.Label;
658    }
659
[6471]660    private void addButton_Click(object sender, System.EventArgs e) {
[6524]661      if (typeSelectorDialog == null) typeSelectorDialog = new TypeSelectorDialog();
662
663      IAlgorithm algorithm = null;
664      if (treeView.SelectedNode != null && (treeView.SelectedNode.Tag is IAlgorithm))
665        algorithm = (IAlgorithm)treeView.SelectedNode.Tag;
666
667      if (algorithm == null) {
[6471]668        typeSelectorDialog.Caption = "Select Optimizer";
669        typeSelectorDialog.TypeSelector.Caption = "Available Optimizers";
670        typeSelectorDialog.TypeSelector.Configure(typeof(IOptimizer), false, true);
[6524]671      } else {
672        typeSelectorDialog.Caption = "Select Problem";
673        typeSelectorDialog.TypeSelector.Caption = "Available Problems";
674        typeSelectorDialog.TypeSelector.Configure(algorithm.ProblemType, false, true);
[6471]675      }
676
677      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
678        try {
[6524]679          if (algorithm == null) {
680            IOptimizer optimizer = (IOptimizer)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
681            if (treeView.SelectedNode == null) Content.Optimizers.Add(optimizer);
682            else {
683              var batchRun = treeView.SelectedNode.Tag as BatchRun;
684              var experiment = treeView.SelectedNode.Tag as Experiment;
685              if (batchRun != null) batchRun.Optimizer = optimizer;
686              else if (experiment != null) experiment.Optimizers.Add(optimizer);
687              else throw new NotSupportedException("Handling for specific type not implemented" + treeView.SelectedNode.Tag.GetType());
688            }
689          } else {
690            IProblem problem = (IProblem)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
691            algorithm.Problem = problem;
[6471]692          }
693        }
694        catch (Exception ex) {
695          ErrorHandling.ShowErrorDialog(this, ex);
696        }
697      }
698    }
699
700    private void moveUpButton_Click(object sender, EventArgs e) {
[6524]701      var optimizer = (IOptimizer)treeView.SelectedNode.Tag;
[6471]702      Experiment experiment = null;
[6524]703      if (treeView.SelectedNode.Parent == null) experiment = Content;
704      else experiment = (Experiment)treeView.SelectedNode.Parent.Tag;
[6471]705
[6524]706      int index = treeView.SelectedNode.Index;
[6471]707      experiment.Optimizers.Reverse(index - 1, 2);
[6524]708      treeView.SelectedNode = treeNodeTagMapping[optimizer].First();
[6471]709      SetEnabledStateOfControls();
[6485]710      UpdateDetailsViewHost();
711      RebuildImageList();
[6471]712    }
713    private void moveDownButton_Click(object sender, EventArgs e) {
[6524]714      var optimizer = (IOptimizer)treeView.SelectedNode.Tag;
[6471]715      Experiment experiment = null;
[6524]716      if (treeView.SelectedNode.Parent == null) experiment = Content;
717      else experiment = (Experiment)treeView.SelectedNode.Parent.Tag;
[6471]718
[6524]719      int index = treeView.SelectedNode.Index;
[6471]720      experiment.Optimizers.Reverse(index, 2);
[6524]721      treeView.SelectedNode = treeNodeTagMapping[optimizer].First();
[6471]722      SetEnabledStateOfControls();
[6485]723      UpdateDetailsViewHost();
724      RebuildImageList();
[6471]725    }
726
[6485]727    private void removeButton_Click(object sender, EventArgs e) {
[6524]728      var treeNode = treeView.SelectedNode;
729      var optimizer = treeNode.Tag as IOptimizer;
[6471]730
731      if (treeNode.Parent == null)
732        Content.Optimizers.Remove(optimizer);
733      else {
734        var batchRun = treeNode.Parent.Tag as BatchRun;
735        var experiment = treeNode.Parent.Tag as Experiment;
736        if (batchRun != null) batchRun.Optimizer = null;
737        else if (experiment != null) experiment.Optimizers.Remove(optimizer);
[6524]738        else throw new NotSupportedException("Handling for specific type not implemented" + treeView.SelectedNode.Tag.GetType());
[6471]739      }
740      SetEnabledStateOfControls();
[6485]741      UpdateDetailsViewHost();
742      RebuildImageList();
[6471]743    }
744
745    private void showDetailsCheckBox_CheckedChanged(object sender, System.EventArgs e) {
746      if (showDetailsCheckBox.Checked) {
747        splitContainer.Panel2Collapsed = false;
[6524]748        detailsGroupBox.Enabled = treeView.SelectedNode != null;
749        detailsViewHost.Content = treeView.SelectedNode != null ? (IContent)treeView.SelectedNode.Tag : null;
[6471]750      } else {
751        splitContainer.Panel2Collapsed = true;
752        detailsViewHost.Content = null;
753      }
754    }
755    #endregion
756
757    #region helpers
[6485]758    private void UpdateDetailsViewHost() {
[6524]759      if (treeView.SelectedNode != null)
760        detailsViewHost.Content = (IContent)treeView.SelectedNode.Tag;
[6485]761      else
762        detailsViewHost.Content = null;
763    }
764
[6471]765    private TreeNode CreateTreeNode(IOptimizer optimizer) {
766      TreeNode node = new TreeNode(optimizer.ToString());
767      node.Tag = optimizer;
[6524]768
769      var algorithm = optimizer as IAlgorithm;
770      if (algorithm != null) {
771        foreach (TreeNode childNode in CreateAlgorithmChildNodes(algorithm))
772          node.Nodes.Add(childNode);
773      }
774
[6471]775      List<TreeNode> nodes;
[6524]776      if (!treeNodeTagMapping.TryGetValue(optimizer, out nodes)) {
[6471]777        nodes = new List<TreeNode>();
[6524]778        treeNodeTagMapping.Add(optimizer, nodes);
779        RegisterNamedItemEvents(optimizer);
[6471]780      }
781      nodes.Add(node);
[6524]782
783      foreach (TreeNode childNode in node.Nodes) {
784        NamedItem namedItem = childNode.Tag as NamedItem;
785        if (namedItem != null) {
786          if (!treeNodeTagMapping.TryGetValue(namedItem, out nodes)) {
787            nodes = new List<TreeNode>();
788            treeNodeTagMapping.Add(namedItem, nodes);
789            RegisterNamedItemEvents(namedItem);
790          }
791          nodes.Add(childNode);
792        }
793      }
[6471]794      return node;
795    }
796
[6524]797    private IEnumerable<TreeNode> CreateAlgorithmChildNodes(IAlgorithm algorithm) {
798      TreeNode problemNode;
799      if (algorithm.Problem != null) {
800        problemNode = new TreeNode(algorithm.Problem.Name);
801        problemNode.Tag = algorithm.Problem;
802      } else {
803        problemNode = new TreeNode("No Problem");
804        problemNode.Tag = null;
805      }
806      TreeNode parametersNode = new TreeNode("Parameters");
807      parametersNode.Tag = algorithm.Parameters;
808      TreeNode resultsNode = new TreeNode("Results");
809      resultsNode.Tag = algorithm.Results;
810
811      yield return problemNode;
812      yield return parametersNode;
813      yield return resultsNode;
814    }
815
[6471]816    private void DisposeTreeNode(TreeNode node) {
[6524]817      var namedItem = node.Tag as INamedItem;
818      if (namedItem == null) return;
819
[6471]820      List<TreeNode> nodes;
[6524]821      if (!treeNodeTagMapping.TryGetValue(namedItem, out nodes))
[6471]822        throw new ArgumentException();
823      nodes.Remove(node);
824      if (nodes.Count == 0) {
[6524]825        treeNodeTagMapping.Remove(namedItem);
826        DeregisterNamedItemEvents(namedItem);
[6471]827      }
828    }
829
830    private IEnumerable<TreeNode> IterateTreeNodes(TreeNode node = null) {
831      TreeNodeCollection nodes;
832      if (node == null)
[6524]833        nodes = treeView.Nodes;
[6471]834      else {
835        nodes = node.Nodes;
836        yield return node;
837      }
838
839      foreach (var childNode in nodes.OfType<TreeNode>())
840        foreach (var n in IterateTreeNodes(childNode))
841          yield return n;
842    }
843
844    private void RebuildImageList() {
845      if (InvokeRequired) {
846        Invoke((Action)RebuildImageList);
847        return;
848      }
849
[6539]850      treeView.BeginUpdate();
851
[6524]852      treeView.ImageList.Images.Clear();
[6539]853      var topLevelNodes = treeView.Nodes.OfType<TreeNode>().ToArray();
854      var nodes = IterateTreeNodes().ToList();
855      treeView.Nodes.Clear();
856
857      foreach (TreeNode treeNode in nodes) {
[6524]858        var item = (IItem)treeNode.Tag;
859        treeView.ImageList.Images.Add(item == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : item.ItemImage);
860        treeNode.ImageIndex = treeView.ImageList.Images.Count - 1;
[6471]861      }
[6539]862      treeView.Nodes.AddRange(topLevelNodes);
863      treeView.EndUpdate();
[6471]864    }
865    #endregion
[6517]866
867
868    public sealed class CustomTreeView : System.Windows.Forms.TreeView {
869      protected override void WndProc(ref System.Windows.Forms.Message m) {
870        const int WM_RBUTTONDOWN = 0x204;
871        if (m.Msg == WM_RBUTTONDOWN) {
872          //Raise your custom event right click event to prevent node highlighting
873          OnRightClick();
874          return;
875        }
876        base.WndProc(ref m);
877      }
878
879      public event EventHandler RightClick;
880      private void OnRightClick() {
881        var handler = RightClick;
882        if (handler != null) RightClick(this, EventArgs.Empty);
883      }
884    }
[6471]885  }
886}
Note: See TracBrowser for help on using the repository browser.