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, 12 years ago

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

File size: 38.1 KB
Line 
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;
30using HeuristicLab.Core;
31using HeuristicLab.Core.Views;
32using HeuristicLab.MainForm;
33using HeuristicLab.PluginInfrastructure;
34
35namespace HeuristicLab.Optimization.Views {
36  public sealed partial class ExperimentTreeView : ItemView {
37    private TypeSelectorDialog typeSelectorDialog;
38    private Dictionary<INamedItem, List<TreeNode>> treeNodeTagMapping;
39
40    public ExperimentTreeView() {
41      InitializeComponent();
42      treeNodeTagMapping = new Dictionary<INamedItem, List<TreeNode>>();
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
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
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);
94      foreach (var optimizer in treeNodeTagMapping.Keys)
95        DeregisterNamedItemEvents(optimizer);
96      base.DeregisterContentEvents();
97    }
98
99    private void RegisterNamedItemEvents(INamedItem namedItem) {
100      namedItem.ToStringChanged += new EventHandler(namedItem_ToStringChanged);
101      namedItem.ItemImageChanged += new EventHandler(namedItem_ItemImageChanged);
102
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) {
110        batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged);
111      } else if (experiment != null) {
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
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) {
130        batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged);
131      } else if (experiment != null) {
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) {
144        treeView.Nodes.Clear();
145      } else {
146        UpdateOptimizerTreeView();
147        treeView.ExpandAll();
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
160    private void algorithm_ProblemChanged(object sender, EventArgs e) {
161      if (InvokeRequired) {
162        Invoke((Action<object, EventArgs>)algorithm_ProblemChanged, sender, e);
163        return;
164      }
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
177      RebuildImageList();
178      UpdateDetailsViewHost();
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;
187      foreach (TreeNode node in treeNodeTagMapping[batchRun]) {
188        foreach (TreeNode childNode in node.Nodes.OfType<TreeNode>().ToList()) {
189          DisposeTreeNode(childNode);
190          childNode.Remove();
191        }
192
193        if (batchRun.Optimizer != null) {
194          UpdateChildTreeNodes(node.Nodes, batchRun);
195          node.Expand();
196        }
197      }
198      RebuildImageList();
199      UpdateDetailsViewHost();
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;
210      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
211      else {
212        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
213        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
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;
235      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
236      else {
237        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
238        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
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();
257      UpdateDetailsViewHost();
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;
267      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
268      else {
269        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
270        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
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();
281      UpdateDetailsViewHost();
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;
291      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
292      else {
293        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
294        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
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();
310      UpdateDetailsViewHost();
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;
320      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { treeView.Nodes };
321      else {
322        Experiment experiment = treeNodeTagMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
323        parentNodes = treeNodeTagMapping[experiment].Select(node => node.Nodes);
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();
339      UpdateDetailsViewHost();
340    }
341
342    private void namedItem_ToStringChanged(object sender, EventArgs e) {
343      if (InvokeRequired) {
344        Invoke((Action<object, EventArgs>)namedItem_ToStringChanged, sender, e);
345        return;
346      }
347      var namedItem = (INamedItem)sender;
348      foreach (TreeNode node in treeNodeTagMapping[namedItem])
349        node.Text = namedItem.ToString();
350    }
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    }
364    #endregion
365
366    protected override void PropagateStateChanges(Control control, Type type, System.Reflection.PropertyInfo propertyInfo) {
367      return;
368    }
369
370    protected override void SetEnabledStateOfControls() {
371      base.SetEnabledStateOfControls();
372      IOptimizer optimizer = null;
373      IAlgorithm algorithm = null;
374      BatchRun batchRun = null;
375      Experiment experiment = null;
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;
390      }
391
392      treeView.Enabled = Content != null;
393      if (parentOptimizer != null) {
394        detailsViewHost.ReadOnly = parentOptimizer.ExecutionState == ExecutionState.Started;
395        detailsViewHost.Locked = parentOptimizer.ExecutionState == ExecutionState.Started;
396      }
397
398      addButton.Enabled = Content != null && !Locked && !ReadOnly &&
399        (treeView.SelectedNode == null || experiment != null || batchRun != null || algorithm != null);
400      moveUpButton.Enabled = Content != null && !Locked && !ReadOnly &&
401        treeView.SelectedNode != null && treeView.SelectedNode.PrevNode != null && parentExperiment != null;
402      moveDownButton.Enabled = Content != null && !Locked && !ReadOnly &&
403        treeView.SelectedNode != null && treeView.SelectedNode.NextNode != null && parentExperiment != null;
404      removeButton.Enabled = Content != null && !Locked && !ReadOnly && optimizer != null;
405    }
406
407    private void UpdateOptimizerTreeView() {
408      treeView.Nodes.Clear();
409      UpdateChildTreeNodes(treeView.Nodes, Content);
410      RebuildImageList();
411    }
412
413    private void UpdateChildTreeNodes(TreeNodeCollection collection, IOptimizer optimizer) {
414      var batchRun = optimizer as BatchRun;
415      var experiment = optimizer as Experiment;
416
417      if (batchRun != null && batchRun.Optimizer != null) UpdateChildTreeNodes(collection, new List<IOptimizer>() { batchRun.Optimizer });
418      else if (experiment != null) UpdateChildTreeNodes(collection, experiment.Optimizers);
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;
434      var item = (IItem)selectedNode.Tag;
435      if (item == null) return;
436
437      DataObject data = new DataObject();
438      data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, item);
439      validDragOperation = true;
440
441      if (ReadOnly || !(item is IOptimizer)) {
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) {
446          var optimizer = (IOptimizer)item;
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) {
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;
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;
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;
483
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      }
490
491      if (batchRun == null && experiment == null && algorithm == null) return;
492
493      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
494
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      }
514
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;
520    }
521
522    private void optimizerTreeView_DragDrop(object sender, DragEventArgs e) {
523      Point coordinates = treeView.PointToClient(new Point(e.X, e.Y));
524      TreeNode node = treeView.GetNodeAt(coordinates);
525      Algorithm algorithm = null;
526      BatchRun batchRun = null;
527      Experiment experiment = null;
528
529      if (node == null) experiment = Content;
530      else {
531        algorithm = node.Tag as Algorithm;
532        batchRun = node.Tag as BatchRun;
533        experiment = node.Tag as Experiment;
534      }
535
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;
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());
547      } else if (data is IEnumerable) {
548        IEnumerable<IOptimizer> optimizers = ((IEnumerable)data).Cast<IOptimizer>();
549        if (e.Effect.HasFlag(DragDropEffects.Copy)) {
550          Cloner cloner = new Cloner();
551          optimizers = optimizers.Select(o => cloner.Clone(o));
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
560    private void optimizerTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
561      if (rightClickOccured) return;
562      if (e.X < e.Node.Bounds.Left || e.X > e.Node.Bounds.Right) return;
563      e.Node.Toggle();
564      IContent optimizer = (IContent)e.Node.Tag;
565      MainFormManager.MainForm.ShowContent(optimizer);
566    }
567    private void optimizerTreeview_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) {
568      if (e.X < e.Node.Bounds.Left || e.X > e.Node.Bounds.Right) return;
569      treeView.SelectedNode = e.Node;
570      detailsViewHost.Content = (IContent)e.Node.Tag;
571      SetEnabledStateOfControls();
572    }
573    private void optimizerTreeView_MouseDown(object sender, MouseEventArgs e) {
574      // enables deselection of treeNodes
575      if (e.Button != MouseButtons.Right) rightClickOccured = false;
576      if (treeView.SelectedNode == null) return;
577      Point coordinates = new Point(e.X, e.Y);
578      TreeNode node = treeView.GetNodeAt(coordinates);
579      if (node == null || coordinates.X < node.Bounds.Left || coordinates.X > node.Bounds.Right) {
580        treeView.SelectedNode = null;
581        detailsViewHost.Content = null;
582        SetEnabledStateOfControls();
583      }
584    }
585
586
587    private void optimizerTreeView_KeyDown(object sender, KeyEventArgs e) {
588      if (ReadOnly) return;
589      if (e.KeyCode != Keys.Delete) return;
590      if (treeView.SelectedNode == null) return;
591      if (!(treeView.SelectedNode.Tag is IOptimizer)) return;
592
593      var treeNode = treeView.SelectedNode;
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);
603        else throw new NotSupportedException("Handling for specific type not implemented" + treeView.SelectedNode.Tag.GetType());
604      }
605      SetEnabledStateOfControls();
606      UpdateDetailsViewHost();
607      RebuildImageList();
608    }
609
610    private bool rightClickOccured = true;
611    private TreeNode toolStripMenuNode = null;
612    private void optimizerTreeView_RightClick(object sender, EventArgs e) {
613      rightClickOccured = true;
614      Point coordinates = treeView.PointToClient(Cursor.Position);
615      toolStripMenuNode = treeView.GetNodeAt(coordinates);
616
617      if (toolStripMenuNode != null && coordinates.X >= toolStripMenuNode.Bounds.Left && coordinates.X <= toolStripMenuNode.Bounds.Right) {
618        treeView.SelectedNode = toolStripMenuNode;
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;
626        EditNodeLabelToolStripMenuItem.Enabled = toolStripMenuNode.Tag != null && toolStripMenuNode.Tag is INamedItem;
627        EditNodeLabelToolStripMenuItem.Visible = toolStripMenuNode.Tag != null && toolStripMenuNode.Tag is INamedItem;
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    }
639    private void EditNodeLabelToolStripMenuItem_Click(object sender, EventArgs e) {
640      if (toolStripMenuNode != null) {
641        if (!toolStripMenuNode.IsEditing) toolStripMenuNode.BeginEdit();
642      }
643    }
644
645
646    private void treeView_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e) {
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;
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
660    private void addButton_Click(object sender, System.EventArgs e) {
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) {
668        typeSelectorDialog.Caption = "Select Optimizer";
669        typeSelectorDialog.TypeSelector.Caption = "Available Optimizers";
670        typeSelectorDialog.TypeSelector.Configure(typeof(IOptimizer), false, true);
671      } else {
672        typeSelectorDialog.Caption = "Select Problem";
673        typeSelectorDialog.TypeSelector.Caption = "Available Problems";
674        typeSelectorDialog.TypeSelector.Configure(algorithm.ProblemType, false, true);
675      }
676
677      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
678        try {
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;
692          }
693        }
694        catch (Exception ex) {
695          ErrorHandling.ShowErrorDialog(this, ex);
696        }
697      }
698    }
699
700    private void moveUpButton_Click(object sender, EventArgs e) {
701      var optimizer = (IOptimizer)treeView.SelectedNode.Tag;
702      Experiment experiment = null;
703      if (treeView.SelectedNode.Parent == null) experiment = Content;
704      else experiment = (Experiment)treeView.SelectedNode.Parent.Tag;
705
706      int index = treeView.SelectedNode.Index;
707      experiment.Optimizers.Reverse(index - 1, 2);
708      treeView.SelectedNode = treeNodeTagMapping[optimizer].First();
709      SetEnabledStateOfControls();
710      UpdateDetailsViewHost();
711      RebuildImageList();
712    }
713    private void moveDownButton_Click(object sender, EventArgs e) {
714      var optimizer = (IOptimizer)treeView.SelectedNode.Tag;
715      Experiment experiment = null;
716      if (treeView.SelectedNode.Parent == null) experiment = Content;
717      else experiment = (Experiment)treeView.SelectedNode.Parent.Tag;
718
719      int index = treeView.SelectedNode.Index;
720      experiment.Optimizers.Reverse(index, 2);
721      treeView.SelectedNode = treeNodeTagMapping[optimizer].First();
722      SetEnabledStateOfControls();
723      UpdateDetailsViewHost();
724      RebuildImageList();
725    }
726
727    private void removeButton_Click(object sender, EventArgs e) {
728      var treeNode = treeView.SelectedNode;
729      var optimizer = treeNode.Tag as IOptimizer;
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);
738        else throw new NotSupportedException("Handling for specific type not implemented" + treeView.SelectedNode.Tag.GetType());
739      }
740      SetEnabledStateOfControls();
741      UpdateDetailsViewHost();
742      RebuildImageList();
743    }
744
745    private void showDetailsCheckBox_CheckedChanged(object sender, System.EventArgs e) {
746      if (showDetailsCheckBox.Checked) {
747        splitContainer.Panel2Collapsed = false;
748        detailsGroupBox.Enabled = treeView.SelectedNode != null;
749        detailsViewHost.Content = treeView.SelectedNode != null ? (IContent)treeView.SelectedNode.Tag : null;
750      } else {
751        splitContainer.Panel2Collapsed = true;
752        detailsViewHost.Content = null;
753      }
754    }
755    #endregion
756
757    #region helpers
758    private void UpdateDetailsViewHost() {
759      if (treeView.SelectedNode != null)
760        detailsViewHost.Content = (IContent)treeView.SelectedNode.Tag;
761      else
762        detailsViewHost.Content = null;
763    }
764
765    private TreeNode CreateTreeNode(IOptimizer optimizer) {
766      TreeNode node = new TreeNode(optimizer.ToString());
767      node.Tag = optimizer;
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
775      List<TreeNode> nodes;
776      if (!treeNodeTagMapping.TryGetValue(optimizer, out nodes)) {
777        nodes = new List<TreeNode>();
778        treeNodeTagMapping.Add(optimizer, nodes);
779        RegisterNamedItemEvents(optimizer);
780      }
781      nodes.Add(node);
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      }
794      return node;
795    }
796
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
816    private void DisposeTreeNode(TreeNode node) {
817      var namedItem = node.Tag as INamedItem;
818      if (namedItem == null) return;
819
820      List<TreeNode> nodes;
821      if (!treeNodeTagMapping.TryGetValue(namedItem, out nodes))
822        throw new ArgumentException();
823      nodes.Remove(node);
824      if (nodes.Count == 0) {
825        treeNodeTagMapping.Remove(namedItem);
826        DeregisterNamedItemEvents(namedItem);
827      }
828    }
829
830    private IEnumerable<TreeNode> IterateTreeNodes(TreeNode node = null) {
831      TreeNodeCollection nodes;
832      if (node == null)
833        nodes = treeView.Nodes;
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
850      treeView.BeginUpdate();
851
852      treeView.ImageList.Images.Clear();
853      var topLevelNodes = treeView.Nodes.OfType<TreeNode>().ToArray();
854      var nodes = IterateTreeNodes().ToList();
855      treeView.Nodes.Clear();
856
857      foreach (TreeNode treeNode in nodes) {
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;
861      }
862      treeView.Nodes.AddRange(topLevelNodes);
863      treeView.EndUpdate();
864    }
865    #endregion
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    }
885  }
886}
Note: See TracBrowser for help on using the repository browser.