Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 6542 was 6542, checked in by mkommend, 12 years ago

#1555: Corrected SelectedItemImage and registering of algorithm events if the problem gets changed.

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