Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1043: Implemented display of calculated repetitions of a batchrun in the experiment tree view by adapting the text of the batchrun node to "Batchrun-Name x/y".

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