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

Last change on this file since 6485 was 6485, checked in by mkommend, 8 years ago

#1555: Added remove by keystroke functionality and refactored the code.

File size: 30.5 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.Views;
31using HeuristicLab.PluginInfrastructure;
32
33namespace HeuristicLab.Optimization.Views {
34  public sealed partial class ExperimentTreeView : ItemView {
35    private TypeSelectorDialog typeSelectorDialog;
36    private Dictionary<IOptimizer, List<TreeNode>> optimizerTreeViewMapping;
37
38    public ExperimentTreeView() {
39      InitializeComponent();
40      optimizerTreeViewMapping = new Dictionary<IOptimizer, List<TreeNode>>();
41    }
42
43    protected override void Dispose(bool disposing) {
44      if (disposing) {
45        if (typeSelectorDialog != null) typeSelectorDialog.Dispose();
46        if (components != null) components.Dispose();
47      }
48      base.Dispose(disposing);
49    }
50
51    public new Experiment Content {
52      get { return (Experiment)base.Content; }
53      set { base.Content = value; }
54    }
55
56    #region events registration
57    protected override void RegisterContentEvents() {
58      base.RegisterContentEvents();
59      Content.ExecutionStateChanged += new EventHandler(Content_ExecutionStateChanged);
60      Content.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
61      Content.Optimizers.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsMoved);
62      Content.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
63      Content.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
64      Content.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
65    }
66
67    protected override void DeregisterContentEvents() {
68      Content.ExecutionStateChanged -= new EventHandler(Content_ExecutionStateChanged);
69      Content.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
70      Content.Optimizers.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsMoved);
71      Content.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
72      Content.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
73      Content.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
74      foreach (var optimizer in optimizerTreeViewMapping.Keys)
75        DeregisterOptimizerEvents(optimizer);
76      base.DeregisterContentEvents();
77    }
78
79    private void RegisterOptimizerEvents(IOptimizer optimizer) {
80      optimizer.ToStringChanged += new EventHandler(optimizer_ToStringChanged);
81      optimizer.ExecutionStateChanged += new EventHandler(optimizer_ExecutionStateChanged);
82
83      var batchRun = optimizer as BatchRun;
84      var experiment = optimizer as Experiment;
85      if (batchRun != null) {
86        batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged);
87      }
88      if (experiment != null) {
89        experiment.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
90        experiment.Optimizers.ItemsMoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsMoved);
91        experiment.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
92        experiment.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
93        experiment.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
94      }
95    }
96
97    private void DeregisterOptimizerEvents(IOptimizer optimizer) {
98      optimizer.ToStringChanged -= new EventHandler(optimizer_ToStringChanged);
99      optimizer.ExecutionStateChanged -= new EventHandler(optimizer_ExecutionStateChanged);
100
101      var batchRun = optimizer as BatchRun;
102      var experiment = optimizer as Experiment;
103      if (batchRun != null) {
104        batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged);
105      }
106      if (experiment != null) {
107        experiment.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
108        experiment.Optimizers.ItemsMoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsMoved);
109        experiment.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
110        experiment.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
111        experiment.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
112      }
113    }
114    #endregion
115
116    protected override void OnContentChanged() {
117      base.OnContentChanged();
118      if (Content == null) {
119        optimizerTreeView.Nodes.Clear();
120      } else {
121        UpdateOptimizerTreeView();
122        optimizerTreeView.ExpandAll();
123      }
124    }
125
126    #region content events
127    private void Content_ExecutionStateChanged(object sender, EventArgs e) {
128      if (InvokeRequired) {
129        Invoke((Action<object, EventArgs>)Content_ExecutionStateChanged, sender, e);
130        return;
131      }
132      RebuildImageList();
133      SetEnabledStateOfControls();
134    }
135
136    private void optimizer_ExecutionStateChanged(object sender, EventArgs e) {
137      if (InvokeRequired) {
138        Invoke((Action<object, EventArgs>)optimizer_ExecutionStateChanged, sender, e);
139        return;
140      }
141      RebuildImageList();
142    }
143
144    private void batchRun_OptimizerChanged(object sender, EventArgs e) {
145      if (InvokeRequired) {
146        Invoke((Action<object, EventArgs>)batchRun_OptimizerChanged, sender, e);
147        return;
148      }
149      var batchRun = (BatchRun)sender;
150      foreach (TreeNode node in optimizerTreeViewMapping[batchRun]) {
151        foreach (TreeNode childNode in node.Nodes) {
152          DisposeTreeNode(childNode);
153          childNode.Remove();
154        }
155
156        if (batchRun.Optimizer != null) {
157          TreeNode childNode = CreateTreeNode(batchRun.Optimizer);
158          UpdateChildTreeNodes(childNode.Nodes, batchRun.Optimizer);
159          node.Nodes.Add(childNode);
160          node.Expand();
161        }
162      }
163      RebuildImageList();
164      UpdateDetailsViewHost();
165    }
166
167    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
168      if (InvokeRequired) {
169        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_ItemsAdded, sender, e);
170        return;
171      }
172
173      var optimizerList = (OptimizerList)sender;
174      IEnumerable<TreeNodeCollection> parentNodes;
175      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { optimizerTreeView.Nodes };
176      else {
177        Experiment experiment = optimizerTreeViewMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
178        parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes);
179      }
180
181      foreach (TreeNodeCollection parentNode in parentNodes) {
182        foreach (var childOptimizer in e.Items) {
183          TreeNode childNode = CreateTreeNode(childOptimizer.Value);
184          UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value);
185          parentNode.Insert(childOptimizer.Index, childNode);
186          childNode.ExpandAll();
187          if (childNode.Parent != null) childNode.Parent.ExpandAll();
188        }
189      }
190      RebuildImageList();
191    }
192    private void Optimizers_ItemsMoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
193      if (InvokeRequired) {
194        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_ItemsMoved, sender, e);
195        return;
196      }
197
198      var optimizerList = (OptimizerList)sender;
199      IEnumerable<TreeNodeCollection> parentNodes;
200      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { optimizerTreeView.Nodes };
201      else {
202        Experiment experiment = optimizerTreeViewMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
203        parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes);
204      }
205
206      foreach (TreeNodeCollection parentNode in parentNodes) {
207        //get all effected child nodes
208        foreach (TreeNode childNode in parentNode.OfType<TreeNode>()
209          .Where(n => e.OldItems.Select(x => x.Value).Contains((IOptimizer)n.Tag)).ToList()) {
210          DisposeTreeNode(childNode);
211          childNode.Remove();
212        }
213
214        foreach (var childOptimizer in e.Items) {
215          TreeNode childNode = CreateTreeNode(childOptimizer.Value);
216          UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value);
217          childNode.ExpandAll();
218          parentNode.Insert(childOptimizer.Index, childNode);
219        }
220      }
221      RebuildImageList();
222      UpdateDetailsViewHost();
223    }
224    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
225      if (InvokeRequired) {
226        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_ItemsRemoved, sender, e);
227        return;
228      }
229
230      var optimizerList = (OptimizerList)sender;
231      IEnumerable<TreeNodeCollection> parentNodes;
232      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { optimizerTreeView.Nodes };
233      else {
234        Experiment experiment = optimizerTreeViewMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
235        parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes);
236      }
237
238      foreach (TreeNodeCollection parentNode in parentNodes) {
239        foreach (var childOptimizer in e.Items) {
240          TreeNode childNode = parentNode[childOptimizer.Index];
241          DisposeTreeNode(childNode);
242          childNode.Remove();
243        }
244      }
245      RebuildImageList();
246      UpdateDetailsViewHost();
247    }
248    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
249      if (InvokeRequired) {
250        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_ItemsReplaced, sender, e);
251        return;
252      }
253
254      var optimizerList = (OptimizerList)sender;
255      IEnumerable<TreeNodeCollection> parentNodes;
256      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { optimizerTreeView.Nodes };
257      else {
258        Experiment experiment = optimizerTreeViewMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
259        parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes);
260      }
261
262      foreach (TreeNodeCollection parentNode in parentNodes) {
263        foreach (var childOptimizer in e.OldItems) {
264          TreeNode childNode = parentNode.Cast<TreeNode>().Where(n => n.Tag == childOptimizer.Value && n.Index == childOptimizer.Index).First();
265          DisposeTreeNode(childNode);
266          childNode.Remove();
267        }
268        foreach (var childOptimizer in e.Items) {
269          TreeNode childNode = CreateTreeNode(childOptimizer.Value);
270          UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value);
271          parentNode.Insert(childOptimizer.Index, childNode);
272        }
273      }
274      RebuildImageList();
275      UpdateDetailsViewHost();
276    }
277    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
278      if (InvokeRequired) {
279        Invoke((Action<object, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>>>)Optimizers_CollectionReset, sender, e);
280        return;
281      }
282
283      var optimizerList = (OptimizerList)sender;
284      IEnumerable<TreeNodeCollection> parentNodes;
285      if (optimizerList == Content.Optimizers) parentNodes = new List<TreeNodeCollection>() { optimizerTreeView.Nodes };
286      else {
287        Experiment experiment = optimizerTreeViewMapping.Keys.OfType<Experiment>().Where(exp => exp.Optimizers == optimizerList).First();
288        parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes);
289      }
290
291      foreach (TreeNodeCollection parentNode in parentNodes) {
292        foreach (var childOptimizer in e.OldItems) {
293          TreeNode childNode = parentNode.Cast<TreeNode>().Where(n => n.Tag == childOptimizer.Value && n.Index == childOptimizer.Index).First();
294          DisposeTreeNode(childNode);
295          childNode.Remove();
296        }
297        foreach (var childOptimizer in e.Items) {
298          TreeNode childNode = CreateTreeNode(childOptimizer.Value);
299          UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value);
300          parentNode.Insert(childOptimizer.Index, childNode);
301        }
302      }
303      RebuildImageList();
304      UpdateDetailsViewHost();
305    }
306
307    private void optimizer_ToStringChanged(object sender, EventArgs e) {
308      if (InvokeRequired) {
309        Invoke((Action<object, EventArgs>)optimizer_ToStringChanged, sender, e);
310        return;
311      }
312      var optimizer = (IOptimizer)sender;
313      foreach (TreeNode node in optimizerTreeViewMapping[optimizer])
314        node.Text = optimizer.ToString();
315    }
316    #endregion
317
318    protected override void SetEnabledStateOfControls() {
319      base.SetEnabledStateOfControls();
320      BatchRun batchRun = null;
321      BatchRun parentBatchRun = null;
322      Experiment experiment = null;
323      if (optimizerTreeView.SelectedNode != null) {
324        batchRun = optimizerTreeView.SelectedNode.Tag as BatchRun;
325        experiment = optimizerTreeView.SelectedNode.Tag as Experiment;
326        if (optimizerTreeView.SelectedNode.Parent != null)
327          parentBatchRun = optimizerTreeView.SelectedNode.Parent.Tag as BatchRun;
328      }
329
330      optimizerTreeView.Enabled = Content != null;
331      detailsViewHost.Enabled = Content != null && optimizerTreeView.SelectedNode != null;
332
333      addButton.Enabled = Content != null && !Locked && !ReadOnly &&
334        (optimizerTreeView.SelectedNode == null || experiment != null || (batchRun != null && batchRun.Optimizer == null));
335      moveUpButton.Enabled = Content != null && !Locked && !ReadOnly &&
336        optimizerTreeView.SelectedNode != null && optimizerTreeView.SelectedNode.PrevNode != null && parentBatchRun == null;
337      moveDownButton.Enabled = Content != null && !Locked && !ReadOnly &&
338        optimizerTreeView.SelectedNode != null && optimizerTreeView.SelectedNode.NextNode != null && parentBatchRun == null;
339      removeButton.Enabled = Content != null && !Locked && !ReadOnly &&
340        optimizerTreeView.SelectedNode != null;
341    }
342
343    private void UpdateOptimizerTreeView() {
344      optimizerTreeView.Nodes.Clear();
345      UpdateChildTreeNodes(optimizerTreeView.Nodes, Content);
346      RebuildImageList();
347    }
348
349
350    private void UpdateChildTreeNodes(TreeNodeCollection collection, IOptimizer optimizer) {
351      var batchRun = optimizer as BatchRun;
352      var experiment = optimizer as Experiment;
353      if (experiment != null) UpdateChildTreeNodes(collection, experiment.Optimizers);
354      else if (batchRun != null && batchRun.Optimizer != null) UpdateChildTreeNodes(collection, new List<IOptimizer>() { batchRun.Optimizer });
355    }
356    private void UpdateChildTreeNodes(TreeNodeCollection collection, IEnumerable<IOptimizer> optimizers) {
357      foreach (IOptimizer optimizer in optimizers) {
358        var node = CreateTreeNode(optimizer);
359        collection.Add(node);
360        UpdateChildTreeNodes(node.Nodes, optimizer);
361      }
362    }
363
364
365    #region drag & drop
366    private void optimizerTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
367      if (Locked) return;
368
369      TreeNode selectedNode = (TreeNode)e.Item;
370      var optimizer = (IOptimizer)selectedNode.Tag;
371      DataObject data = new DataObject();
372      data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, optimizer);
373      validDragOperation = true;
374
375      if (ReadOnly) {
376        DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
377      } else {
378        DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
379        if ((result & DragDropEffects.Move) == DragDropEffects.Move) {
380          if (selectedNode.Parent == null) Content.Optimizers.Remove(optimizer);
381          else {
382            var parentOptimizer = (IOptimizer)selectedNode.Parent.Tag;
383            var parentBatchRun = parentOptimizer as BatchRun;
384            var parentExperiment = parentOptimizer as Experiment;
385            if (parentBatchRun != null) parentBatchRun.Optimizer = null;
386            else if (parentExperiment != null) parentExperiment.Optimizers.Remove(optimizer);
387            else throw new NotSupportedException("Handling for specific type not implemented" + parentOptimizer.GetType());
388          }
389          SetEnabledStateOfControls();
390          UpdateDetailsViewHost();
391          RebuildImageList();
392        }
393      }
394    }
395
396    private bool validDragOperation = false;
397    private void optimizerTreeView_DragEnter(object sender, DragEventArgs e) {
398      validDragOperation = false;
399      if (!ReadOnly) {
400        if ((e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) is IOptimizer)) validDragOperation = true;
401        else if (e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) is IEnumerable) {
402          validDragOperation = true;
403          IEnumerable items = (IEnumerable)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
404          foreach (object item in items)
405            validDragOperation = validDragOperation && (item is IOptimizer);
406        }
407      }
408    }
409    private void optimizerTreeView_DragOver(object sender, DragEventArgs e) {
410      e.Effect = DragDropEffects.None;
411      if (validDragOperation) {
412        Point coordinates = optimizerTreeView.PointToClient(new Point(e.X, e.Y));
413        TreeNode node = optimizerTreeView.GetNodeAt(coordinates);
414        Experiment experiment = null;
415        BatchRun batchRun = null;
416
417        if (node == null) experiment = Content;
418        else {
419          experiment = node.Tag as Experiment;
420          batchRun = node.Tag as BatchRun;
421        }
422
423        if (batchRun == null && experiment == null) return;
424        if (batchRun != null) {
425          var optimizer = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IOptimizer;
426          if (optimizer == null) return;
427          if (batchRun.Optimizer != null) return;
428          if (optimizer.GetObjectGraphObjects().OfType<IOptimizer>().Contains(batchRun)) return;
429        }
430
431        //do not allow recursive nesting of contents
432        if (experiment != null) {
433          var optimizer = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IOptimizer;
434          IEnumerable<IOptimizer> optimizers = null;
435          var enumerable = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable;
436          if (enumerable != null) optimizers = enumerable.Cast<IOptimizer>();
437
438          if (optimizer != null && optimizer.GetObjectGraphObjects().OfType<IOptimizer>().Contains(experiment)) return;
439          if (optimizers != null && optimizers.GetObjectGraphObjects().OfType<IOptimizer>().Contains(experiment)) return;
440        }
441
442        if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link;  // ALT key
443        else if ((e.KeyState & 4) == 4) e.Effect = DragDropEffects.Move;  // SHIFT key
444        else if (e.AllowedEffect.HasFlag(DragDropEffects.Copy)) e.Effect = DragDropEffects.Copy;
445        else if (e.AllowedEffect.HasFlag(DragDropEffects.Move)) e.Effect = DragDropEffects.Move;
446        else if (e.AllowedEffect.HasFlag(DragDropEffects.Link)) e.Effect = DragDropEffects.Link;
447      }
448    }
449    private void optimizerTreeView_DragDrop(object sender, DragEventArgs e) {
450      Point coordinates = optimizerTreeView.PointToClient(new Point(e.X, e.Y));
451      TreeNode node = optimizerTreeView.GetNodeAt(coordinates);
452      Experiment experiment = null;
453      BatchRun batchRun = null;
454
455      if (node == null) experiment = Content;
456      else {
457        experiment = node.Tag as Experiment;
458        batchRun = node.Tag as BatchRun;
459      }
460
461      if (e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) is IOptimizer) {
462        IOptimizer optimizer = (IOptimizer)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
463        if (e.Effect.HasFlag(DragDropEffects.Copy)) optimizer = (IOptimizer)optimizer.Clone();
464        if (batchRun != null) batchRun.Optimizer = optimizer;
465        else if (experiment != null) experiment.Optimizers.Add(optimizer);
466        else throw new NotSupportedException("Handling for specific type not implemented" + node.Tag.GetType());
467      } else if (e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) is IEnumerable) {
468        IEnumerable<IOptimizer> optimizers = ((IEnumerable)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat)).Cast<IOptimizer>();
469        if (e.Effect.HasFlag(DragDropEffects.Copy)) {
470          Cloner cloner = new Cloner();
471          optimizers = optimizers.Select(o => (IOptimizer)o.Clone(cloner));
472        }
473        if (experiment != null) experiment.Optimizers.AddRange(optimizers);
474        else throw new NotSupportedException("Handling for specific type not implemented" + node.Tag.GetType());
475      }
476    }
477    #endregion
478
479    #region control events
480    private void optimizerTreeview_MouseClick(object sender, MouseEventArgs e) {
481      Point coordinates = new Point(e.X, e.Y);
482      TreeNode selectedNode = optimizerTreeView.GetNodeAt(coordinates);
483      if (selectedNode != null) {
484        optimizerTreeView.SelectedNode = selectedNode;
485        detailsViewHost.Content = (IOptimizer)selectedNode.Tag;
486        SetEnabledStateOfControls();
487      }
488    }
489    private void optimizerTreeView_MouseDown(object sender, MouseEventArgs e) {
490      // enables deselection of treeNodes
491      if (optimizerTreeView.SelectedNode == null) return;
492      Point coordinates = new Point(e.X, e.Y);
493      if (e.Button == System.Windows.Forms.MouseButtons.Left && optimizerTreeView.GetNodeAt(coordinates) == null) {
494        optimizerTreeView.SelectedNode = null;
495        detailsViewHost.Content = null;
496        SetEnabledStateOfControls();
497      }
498    }
499
500    private void optimizerTreeView_KeyDown(object sender, KeyEventArgs e) {
501      if (ReadOnly) return;
502      if (optimizerTreeView.SelectedNode == null) return;
503      if (e.KeyCode != Keys.Delete) return;
504
505      var treeNode = optimizerTreeView.SelectedNode;
506      var optimizer = (IOptimizer)treeNode.Tag;
507
508      if (treeNode.Parent == null)
509        Content.Optimizers.Remove(optimizer);
510      else {
511        var batchRun = treeNode.Parent.Tag as BatchRun;
512        var experiment = treeNode.Parent.Tag as Experiment;
513        if (batchRun != null) batchRun.Optimizer = null;
514        else if (experiment != null) experiment.Optimizers.Remove(optimizer);
515        else throw new NotSupportedException("Handling for specific type not implemented" + optimizerTreeView.SelectedNode.Tag.GetType());
516      }
517      SetEnabledStateOfControls();
518      UpdateDetailsViewHost();
519      RebuildImageList();
520    }
521
522    private void addButton_Click(object sender, System.EventArgs e) {
523      if (typeSelectorDialog == null) {
524        typeSelectorDialog = new TypeSelectorDialog();
525        typeSelectorDialog.Caption = "Select Optimizer";
526        typeSelectorDialog.TypeSelector.Caption = "Available Optimizers";
527        typeSelectorDialog.TypeSelector.Configure(typeof(IOptimizer), false, true);
528      }
529
530      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
531        try {
532          IOptimizer optimizer = (IOptimizer)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
533          if (optimizerTreeView.SelectedNode == null) Content.Optimizers.Add(optimizer);
534          else {
535            var batchRun = optimizerTreeView.SelectedNode.Tag as BatchRun;
536            var experiment = optimizerTreeView.SelectedNode.Tag as Experiment;
537            if (batchRun != null) batchRun.Optimizer = optimizer;
538            else if (experiment != null) experiment.Optimizers.Add(optimizer);
539            else throw new NotSupportedException("Handling for specific type not implemented" + optimizerTreeView.SelectedNode.Tag.GetType());
540          }
541        }
542        catch (Exception ex) {
543          ErrorHandling.ShowErrorDialog(this, ex);
544        }
545      }
546    }
547
548    private void moveUpButton_Click(object sender, EventArgs e) {
549      var optimizer = optimizerTreeView.SelectedNode.Tag as IOptimizer;
550      Experiment experiment = null;
551      if (optimizerTreeView.SelectedNode.Parent == null) experiment = Content;
552      else experiment = (Experiment)optimizerTreeView.SelectedNode.Parent.Tag;
553
554      int index = optimizerTreeView.SelectedNode.Index;
555      experiment.Optimizers.Reverse(index - 1, 2);
556      optimizerTreeView.SelectedNode = optimizerTreeViewMapping[optimizer].First();
557      SetEnabledStateOfControls();
558      UpdateDetailsViewHost();
559      RebuildImageList();
560    }
561    private void moveDownButton_Click(object sender, EventArgs e) {
562      var optimizer = optimizerTreeView.SelectedNode.Tag as IOptimizer;
563      Experiment experiment = null;
564      if (optimizerTreeView.SelectedNode.Parent == null) experiment = Content;
565      else experiment = (Experiment)optimizerTreeView.SelectedNode.Parent.Tag;
566
567      int index = optimizerTreeView.SelectedNode.Index;
568      experiment.Optimizers.Reverse(index, 2);
569      optimizerTreeView.SelectedNode = optimizerTreeViewMapping[optimizer].First();
570      SetEnabledStateOfControls();
571      UpdateDetailsViewHost();
572      RebuildImageList();
573    }
574
575    private void removeButton_Click(object sender, EventArgs e) {
576      var treeNode = optimizerTreeView.SelectedNode;
577      var optimizer = (IOptimizer)treeNode.Tag;
578
579      if (treeNode.Parent == null)
580        Content.Optimizers.Remove(optimizer);
581      else {
582        var batchRun = treeNode.Parent.Tag as BatchRun;
583        var experiment = treeNode.Parent.Tag as Experiment;
584        if (batchRun != null) batchRun.Optimizer = null;
585        else if (experiment != null) experiment.Optimizers.Remove(optimizer);
586        else throw new NotSupportedException("Handling for specific type not implemented" + optimizerTreeView.SelectedNode.Tag.GetType());
587      }
588      SetEnabledStateOfControls();
589      UpdateDetailsViewHost();
590      RebuildImageList();
591    }
592
593    private void showDetailsCheckBox_CheckedChanged(object sender, System.EventArgs e) {
594      if (showDetailsCheckBox.Checked) {
595        splitContainer.Panel2Collapsed = false;
596        detailsGroupBox.Enabled = optimizerTreeView.SelectedNode != null;
597        detailsViewHost.Content = optimizerTreeView.SelectedNode != null ? (IOptimizer)optimizerTreeView.SelectedNode.Tag : null;
598      } else {
599        splitContainer.Panel2Collapsed = true;
600        detailsViewHost.Content = null;
601      }
602    }
603    #endregion
604
605    #region helpers
606    private void UpdateDetailsViewHost() {
607      if (optimizerTreeView.SelectedNode != null)
608        detailsViewHost.Content = (IOptimizer)optimizerTreeView.SelectedNode.Tag;
609      else
610        detailsViewHost.Content = null;
611    }
612
613    private TreeNode CreateTreeNode(IOptimizer optimizer) {
614      TreeNode node = new TreeNode(optimizer.ToString());
615      node.Tag = optimizer;
616      List<TreeNode> nodes;
617      if (!optimizerTreeViewMapping.TryGetValue(optimizer, out nodes)) {
618        nodes = new List<TreeNode>();
619        optimizerTreeViewMapping.Add(optimizer, nodes);
620        RegisterOptimizerEvents(optimizer);
621      }
622      nodes.Add(node);
623      return node;
624    }
625
626    private void DisposeTreeNode(TreeNode node) {
627      var optimizer = (IOptimizer)node.Tag;
628      List<TreeNode> nodes;
629      if (!optimizerTreeViewMapping.TryGetValue(optimizer, out nodes))
630        throw new ArgumentException();
631      nodes.Remove(node);
632      if (nodes.Count == 0) {
633        optimizerTreeViewMapping.Remove(optimizer);
634        DeregisterOptimizerEvents(optimizer);
635      }
636    }
637
638    private IEnumerable<TreeNode> IterateTreeNodes(TreeNode node = null) {
639      TreeNodeCollection nodes;
640      if (node == null)
641        nodes = optimizerTreeView.Nodes;
642      else {
643        nodes = node.Nodes;
644        yield return node;
645      }
646
647      foreach (var childNode in nodes.OfType<TreeNode>())
648        foreach (var n in IterateTreeNodes(childNode))
649          yield return n;
650    }
651
652    private void RebuildImageList() {
653      if (InvokeRequired) {
654        Invoke((Action)RebuildImageList);
655        return;
656      }
657
658      optimizerTreeView.ImageList.Images.Clear();
659      foreach (TreeNode treeNode in IterateTreeNodes()) {
660        var optimizer = (IOptimizer)treeNode.Tag;
661        optimizerTreeView.ImageList.Images.Add(optimizer == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : optimizer.ItemImage);
662        treeNode.ImageIndex = optimizerTreeView.ImageList.Images.Count - 1;
663        treeNode.SelectedImageIndex = treeNode.ImageIndex;
664      }
665    }
666    #endregion
667  }
668}
Note: See TracBrowser for help on using the repository browser.