#region License Information /* HeuristicLab * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core.Views; using HeuristicLab.MainForm; using HeuristicLab.PluginInfrastructure; namespace HeuristicLab.Optimization.Views { public sealed partial class ExperimentTreeView : ItemView { private TypeSelectorDialog typeSelectorDialog; private Dictionary> optimizerTreeViewMapping; public ExperimentTreeView() { InitializeComponent(); optimizerTreeViewMapping = new Dictionary>(); } protected override void Dispose(bool disposing) { if (disposing) { if (typeSelectorDialog != null) typeSelectorDialog.Dispose(); if (components != null) components.Dispose(); } base.Dispose(disposing); } #region necessary code to handle dock correctly regarding the expanded nodes bool[] expandendedState; protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (expandendedState == null) return; var nodes = IterateTreeNodes().ToList(); for (int i = 0; i < nodes.Count; i++) if (expandendedState[i]) nodes[i].Expand(); } protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed(e); var nodes = IterateTreeNodes().ToList(); expandendedState = new bool[nodes.Count]; for (int i = 0; i < nodes.Count; i++) expandendedState[i] = nodes[i].IsExpanded; } #endregion public new Experiment Content { get { return (Experiment)base.Content; } set { base.Content = value; } } #region events registration protected override void RegisterContentEvents() { base.RegisterContentEvents(); Content.ExecutionStateChanged += new EventHandler(Content_ExecutionStateChanged); Content.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler>(Optimizers_ItemsAdded); Content.Optimizers.ItemsMoved += new CollectionItemsChangedEventHandler>(Optimizers_ItemsMoved); Content.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler>(Optimizers_ItemsRemoved); Content.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler>(Optimizers_ItemsReplaced); Content.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler>(Optimizers_CollectionReset); } protected override void DeregisterContentEvents() { Content.ExecutionStateChanged -= new EventHandler(Content_ExecutionStateChanged); Content.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler>(Optimizers_ItemsAdded); Content.Optimizers.ItemsMoved -= new CollectionItemsChangedEventHandler>(Optimizers_ItemsMoved); Content.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler>(Optimizers_ItemsRemoved); Content.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler>(Optimizers_ItemsReplaced); Content.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler>(Optimizers_CollectionReset); foreach (var optimizer in optimizerTreeViewMapping.Keys) DeregisterOptimizerEvents(optimizer); base.DeregisterContentEvents(); } private void RegisterOptimizerEvents(IOptimizer optimizer) { optimizer.ToStringChanged += new EventHandler(optimizer_ToStringChanged); optimizer.ExecutionStateChanged += new EventHandler(optimizer_ExecutionStateChanged); var batchRun = optimizer as BatchRun; var experiment = optimizer as Experiment; if (batchRun != null) { batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged); } if (experiment != null) { experiment.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler>(Optimizers_ItemsAdded); experiment.Optimizers.ItemsMoved += new CollectionItemsChangedEventHandler>(Optimizers_ItemsMoved); experiment.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler>(Optimizers_ItemsRemoved); experiment.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler>(Optimizers_ItemsReplaced); experiment.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler>(Optimizers_CollectionReset); } } private void DeregisterOptimizerEvents(IOptimizer optimizer) { optimizer.ToStringChanged -= new EventHandler(optimizer_ToStringChanged); optimizer.ExecutionStateChanged -= new EventHandler(optimizer_ExecutionStateChanged); var batchRun = optimizer as BatchRun; var experiment = optimizer as Experiment; if (batchRun != null) { batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged); } if (experiment != null) { experiment.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler>(Optimizers_ItemsAdded); experiment.Optimizers.ItemsMoved -= new CollectionItemsChangedEventHandler>(Optimizers_ItemsMoved); experiment.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler>(Optimizers_ItemsRemoved); experiment.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler>(Optimizers_ItemsReplaced); experiment.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler>(Optimizers_CollectionReset); } } #endregion protected override void OnContentChanged() { base.OnContentChanged(); if (Content == null) { optimizerTreeView.Nodes.Clear(); } else { UpdateOptimizerTreeView(); optimizerTreeView.ExpandAll(); } } #region content events private void Content_ExecutionStateChanged(object sender, EventArgs e) { if (InvokeRequired) { Invoke((Action)Content_ExecutionStateChanged, sender, e); return; } RebuildImageList(); SetEnabledStateOfControls(); } private void optimizer_ExecutionStateChanged(object sender, EventArgs e) { if (InvokeRequired) { Invoke((Action)optimizer_ExecutionStateChanged, sender, e); return; } RebuildImageList(); } private void batchRun_OptimizerChanged(object sender, EventArgs e) { if (InvokeRequired) { Invoke((Action)batchRun_OptimizerChanged, sender, e); return; } var batchRun = (BatchRun)sender; foreach (TreeNode node in optimizerTreeViewMapping[batchRun]) { foreach (TreeNode childNode in node.Nodes) { DisposeTreeNode(childNode); childNode.Remove(); } if (batchRun.Optimizer != null) { TreeNode childNode = CreateTreeNode(batchRun.Optimizer); UpdateChildTreeNodes(childNode.Nodes, batchRun.Optimizer); node.Nodes.Add(childNode); node.Expand(); } } RebuildImageList(); UpdateDetailsViewHost(); } private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) { Invoke((Action>>)Optimizers_ItemsAdded, sender, e); return; } var optimizerList = (OptimizerList)sender; IEnumerable parentNodes; if (optimizerList == Content.Optimizers) parentNodes = new List() { optimizerTreeView.Nodes }; else { Experiment experiment = optimizerTreeViewMapping.Keys.OfType().Where(exp => exp.Optimizers == optimizerList).First(); parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes); } foreach (TreeNodeCollection parentNode in parentNodes) { foreach (var childOptimizer in e.Items) { TreeNode childNode = CreateTreeNode(childOptimizer.Value); UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value); parentNode.Insert(childOptimizer.Index, childNode); childNode.ExpandAll(); if (childNode.Parent != null) childNode.Parent.ExpandAll(); } } RebuildImageList(); } private void Optimizers_ItemsMoved(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) { Invoke((Action>>)Optimizers_ItemsMoved, sender, e); return; } var optimizerList = (OptimizerList)sender; IEnumerable parentNodes; if (optimizerList == Content.Optimizers) parentNodes = new List() { optimizerTreeView.Nodes }; else { Experiment experiment = optimizerTreeViewMapping.Keys.OfType().Where(exp => exp.Optimizers == optimizerList).First(); parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes); } foreach (TreeNodeCollection parentNode in parentNodes) { //get all effected child nodes foreach (TreeNode childNode in parentNode.OfType() .Where(n => e.OldItems.Select(x => x.Value).Contains((IOptimizer)n.Tag)).ToList()) { DisposeTreeNode(childNode); childNode.Remove(); } foreach (var childOptimizer in e.Items) { TreeNode childNode = CreateTreeNode(childOptimizer.Value); UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value); childNode.ExpandAll(); parentNode.Insert(childOptimizer.Index, childNode); } } RebuildImageList(); UpdateDetailsViewHost(); } private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) { Invoke((Action>>)Optimizers_ItemsRemoved, sender, e); return; } var optimizerList = (OptimizerList)sender; IEnumerable parentNodes; if (optimizerList == Content.Optimizers) parentNodes = new List() { optimizerTreeView.Nodes }; else { Experiment experiment = optimizerTreeViewMapping.Keys.OfType().Where(exp => exp.Optimizers == optimizerList).First(); parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes); } foreach (TreeNodeCollection parentNode in parentNodes) { foreach (var childOptimizer in e.Items) { TreeNode childNode = parentNode[childOptimizer.Index]; DisposeTreeNode(childNode); childNode.Remove(); } } RebuildImageList(); UpdateDetailsViewHost(); } private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) { Invoke((Action>>)Optimizers_ItemsReplaced, sender, e); return; } var optimizerList = (OptimizerList)sender; IEnumerable parentNodes; if (optimizerList == Content.Optimizers) parentNodes = new List() { optimizerTreeView.Nodes }; else { Experiment experiment = optimizerTreeViewMapping.Keys.OfType().Where(exp => exp.Optimizers == optimizerList).First(); parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes); } foreach (TreeNodeCollection parentNode in parentNodes) { foreach (var childOptimizer in e.OldItems) { TreeNode childNode = parentNode.Cast().Where(n => n.Tag == childOptimizer.Value && n.Index == childOptimizer.Index).First(); DisposeTreeNode(childNode); childNode.Remove(); } foreach (var childOptimizer in e.Items) { TreeNode childNode = CreateTreeNode(childOptimizer.Value); UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value); parentNode.Insert(childOptimizer.Index, childNode); } } RebuildImageList(); UpdateDetailsViewHost(); } private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs> e) { if (InvokeRequired) { Invoke((Action>>)Optimizers_CollectionReset, sender, e); return; } var optimizerList = (OptimizerList)sender; IEnumerable parentNodes; if (optimizerList == Content.Optimizers) parentNodes = new List() { optimizerTreeView.Nodes }; else { Experiment experiment = optimizerTreeViewMapping.Keys.OfType().Where(exp => exp.Optimizers == optimizerList).First(); parentNodes = optimizerTreeViewMapping[experiment].Select(node => node.Nodes); } foreach (TreeNodeCollection parentNode in parentNodes) { foreach (var childOptimizer in e.OldItems) { TreeNode childNode = parentNode.Cast().Where(n => n.Tag == childOptimizer.Value && n.Index == childOptimizer.Index).First(); DisposeTreeNode(childNode); childNode.Remove(); } foreach (var childOptimizer in e.Items) { TreeNode childNode = CreateTreeNode(childOptimizer.Value); UpdateChildTreeNodes(childNode.Nodes, childOptimizer.Value); parentNode.Insert(childOptimizer.Index, childNode); } } RebuildImageList(); UpdateDetailsViewHost(); } private void optimizer_ToStringChanged(object sender, EventArgs e) { if (InvokeRequired) { Invoke((Action)optimizer_ToStringChanged, sender, e); return; } var optimizer = (IOptimizer)sender; foreach (TreeNode node in optimizerTreeViewMapping[optimizer]) node.Text = optimizer.ToString(); } #endregion protected override void SetEnabledStateOfControls() { base.SetEnabledStateOfControls(); BatchRun batchRun = null; BatchRun parentBatchRun = null; Experiment experiment = null; if (optimizerTreeView.SelectedNode != null) { batchRun = optimizerTreeView.SelectedNode.Tag as BatchRun; experiment = optimizerTreeView.SelectedNode.Tag as Experiment; if (optimizerTreeView.SelectedNode.Parent != null) parentBatchRun = optimizerTreeView.SelectedNode.Parent.Tag as BatchRun; } optimizerTreeView.Enabled = Content != null; detailsViewHost.Enabled = Content != null && optimizerTreeView.SelectedNode != null; addButton.Enabled = Content != null && !Locked && !ReadOnly && (optimizerTreeView.SelectedNode == null || experiment != null || (batchRun != null && batchRun.Optimizer == null)); moveUpButton.Enabled = Content != null && !Locked && !ReadOnly && optimizerTreeView.SelectedNode != null && optimizerTreeView.SelectedNode.PrevNode != null && parentBatchRun == null; moveDownButton.Enabled = Content != null && !Locked && !ReadOnly && optimizerTreeView.SelectedNode != null && optimizerTreeView.SelectedNode.NextNode != null && parentBatchRun == null; removeButton.Enabled = Content != null && !Locked && !ReadOnly && optimizerTreeView.SelectedNode != null; } private void UpdateOptimizerTreeView() { optimizerTreeView.Nodes.Clear(); UpdateChildTreeNodes(optimizerTreeView.Nodes, Content); RebuildImageList(); } private void UpdateChildTreeNodes(TreeNodeCollection collection, IOptimizer optimizer) { var batchRun = optimizer as BatchRun; var experiment = optimizer as Experiment; if (experiment != null) UpdateChildTreeNodes(collection, experiment.Optimizers); else if (batchRun != null && batchRun.Optimizer != null) UpdateChildTreeNodes(collection, new List() { batchRun.Optimizer }); } private void UpdateChildTreeNodes(TreeNodeCollection collection, IEnumerable optimizers) { foreach (IOptimizer optimizer in optimizers) { var node = CreateTreeNode(optimizer); collection.Add(node); UpdateChildTreeNodes(node.Nodes, optimizer); } } #region drag & drop private void optimizerTreeView_ItemDrag(object sender, ItemDragEventArgs e) { if (Locked) return; TreeNode selectedNode = (TreeNode)e.Item; var optimizer = (IOptimizer)selectedNode.Tag; DataObject data = new DataObject(); data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, optimizer); validDragOperation = true; if (ReadOnly) { DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link); } else { DragDropEffects result = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move); if ((result & DragDropEffects.Move) == DragDropEffects.Move) { if (selectedNode.Parent == null) Content.Optimizers.Remove(optimizer); else { var parentOptimizer = (IOptimizer)selectedNode.Parent.Tag; var parentBatchRun = parentOptimizer as BatchRun; var parentExperiment = parentOptimizer as Experiment; if (parentBatchRun != null) parentBatchRun.Optimizer = null; else if (parentExperiment != null) parentExperiment.Optimizers.Remove(optimizer); else throw new NotSupportedException("Handling for specific type not implemented" + parentOptimizer.GetType()); } SetEnabledStateOfControls(); UpdateDetailsViewHost(); RebuildImageList(); } } } private bool validDragOperation = false; private void optimizerTreeView_DragEnter(object sender, DragEventArgs e) { validDragOperation = false; if (!ReadOnly) { if ((e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) is IOptimizer)) validDragOperation = true; else if (e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) is IEnumerable) { validDragOperation = true; IEnumerable items = (IEnumerable)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat); foreach (object item in items) validDragOperation = validDragOperation && (item is IOptimizer); } } } private void optimizerTreeView_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.None; if (validDragOperation) { Point coordinates = optimizerTreeView.PointToClient(new Point(e.X, e.Y)); TreeNode node = optimizerTreeView.GetNodeAt(coordinates); Experiment experiment = null; BatchRun batchRun = null; if (node == null) experiment = Content; else { experiment = node.Tag as Experiment; batchRun = node.Tag as BatchRun; } if (batchRun == null && experiment == null) return; if (batchRun != null) { var optimizer = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IOptimizer; if (optimizer == null) return; if (batchRun.Optimizer != null) return; if (optimizer.GetObjectGraphObjects().OfType().Contains(batchRun)) return; } //do not allow recursive nesting of contents if (experiment != null) { var optimizer = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IOptimizer; IEnumerable optimizers = null; var enumerable = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as IEnumerable; if (enumerable != null) optimizers = enumerable.Cast(); if (optimizer != null && optimizer.GetObjectGraphObjects().OfType().Contains(experiment)) return; if (optimizers != null && optimizers.GetObjectGraphObjects().OfType().Contains(experiment)) return; } if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Link; // ALT key else if ((e.KeyState & 4) == 4) e.Effect = DragDropEffects.Move; // SHIFT key else if (e.AllowedEffect.HasFlag(DragDropEffects.Copy)) e.Effect = DragDropEffects.Copy; else if (e.AllowedEffect.HasFlag(DragDropEffects.Move)) e.Effect = DragDropEffects.Move; else if (e.AllowedEffect.HasFlag(DragDropEffects.Link)) e.Effect = DragDropEffects.Link; } } private void optimizerTreeView_DragDrop(object sender, DragEventArgs e) { Point coordinates = optimizerTreeView.PointToClient(new Point(e.X, e.Y)); TreeNode node = optimizerTreeView.GetNodeAt(coordinates); Experiment experiment = null; BatchRun batchRun = null; if (node == null) experiment = Content; else { experiment = node.Tag as Experiment; batchRun = node.Tag as BatchRun; } if (e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) is IOptimizer) { IOptimizer optimizer = (IOptimizer)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat); if (e.Effect.HasFlag(DragDropEffects.Copy)) optimizer = (IOptimizer)optimizer.Clone(); if (batchRun != null) batchRun.Optimizer = optimizer; else if (experiment != null) experiment.Optimizers.Add(optimizer); else throw new NotSupportedException("Handling for specific type not implemented" + node.Tag.GetType()); } else if (e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) is IEnumerable) { IEnumerable optimizers = ((IEnumerable)e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat)).Cast(); if (e.Effect.HasFlag(DragDropEffects.Copy)) { Cloner cloner = new Cloner(); optimizers = optimizers.Select(o => (IOptimizer)o.Clone(cloner)); } if (experiment != null) experiment.Optimizers.AddRange(optimizers); else throw new NotSupportedException("Handling for specific type not implemented" + node.Tag.GetType()); } } #endregion #region control events private void optimizerTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.X < e.Node.Bounds.Left || e.X > e.Node.Bounds.Right) return; optimizerTreeView.SelectedNode.Toggle(); IOptimizer optimizer = (IOptimizer)e.Node.Tag; MainFormManager.MainForm.ShowContent(optimizer); } private void optimizerTreeview_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.X < e.Node.Bounds.Left || e.X > e.Node.Bounds.Right) return; optimizerTreeView.SelectedNode = e.Node; detailsViewHost.Content = (IOptimizer)e.Node.Tag; SetEnabledStateOfControls(); } private void optimizerTreeView_MouseDown(object sender, MouseEventArgs e) { // enables deselection of treeNodes if (e.Button != System.Windows.Forms.MouseButtons.Left) return; if (optimizerTreeView.SelectedNode == null) return; Point coordinates = new Point(e.X, e.Y); TreeNode node = optimizerTreeView.GetNodeAt(coordinates); if (node == null || coordinates.X < node.Bounds.Left || coordinates.X > node.Bounds.Right) { optimizerTreeView.SelectedNode = null; detailsViewHost.Content = null; SetEnabledStateOfControls(); } } private void optimizerTreeView_KeyDown(object sender, KeyEventArgs e) { if (ReadOnly) return; if (optimizerTreeView.SelectedNode == null) return; if (e.KeyCode != Keys.Delete) return; var treeNode = optimizerTreeView.SelectedNode; var optimizer = (IOptimizer)treeNode.Tag; if (treeNode.Parent == null) Content.Optimizers.Remove(optimizer); else { var batchRun = treeNode.Parent.Tag as BatchRun; var experiment = treeNode.Parent.Tag as Experiment; if (batchRun != null) batchRun.Optimizer = null; else if (experiment != null) experiment.Optimizers.Remove(optimizer); else throw new NotSupportedException("Handling for specific type not implemented" + optimizerTreeView.SelectedNode.Tag.GetType()); } SetEnabledStateOfControls(); UpdateDetailsViewHost(); RebuildImageList(); } private void addButton_Click(object sender, System.EventArgs e) { if (typeSelectorDialog == null) { typeSelectorDialog = new TypeSelectorDialog(); typeSelectorDialog.Caption = "Select Optimizer"; typeSelectorDialog.TypeSelector.Caption = "Available Optimizers"; typeSelectorDialog.TypeSelector.Configure(typeof(IOptimizer), false, true); } if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) { try { IOptimizer optimizer = (IOptimizer)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType(); if (optimizerTreeView.SelectedNode == null) Content.Optimizers.Add(optimizer); else { var batchRun = optimizerTreeView.SelectedNode.Tag as BatchRun; var experiment = optimizerTreeView.SelectedNode.Tag as Experiment; if (batchRun != null) batchRun.Optimizer = optimizer; else if (experiment != null) experiment.Optimizers.Add(optimizer); else throw new NotSupportedException("Handling for specific type not implemented" + optimizerTreeView.SelectedNode.Tag.GetType()); } } catch (Exception ex) { ErrorHandling.ShowErrorDialog(this, ex); } } } private void moveUpButton_Click(object sender, EventArgs e) { var optimizer = optimizerTreeView.SelectedNode.Tag as IOptimizer; Experiment experiment = null; if (optimizerTreeView.SelectedNode.Parent == null) experiment = Content; else experiment = (Experiment)optimizerTreeView.SelectedNode.Parent.Tag; int index = optimizerTreeView.SelectedNode.Index; experiment.Optimizers.Reverse(index - 1, 2); optimizerTreeView.SelectedNode = optimizerTreeViewMapping[optimizer].First(); SetEnabledStateOfControls(); UpdateDetailsViewHost(); RebuildImageList(); } private void moveDownButton_Click(object sender, EventArgs e) { var optimizer = optimizerTreeView.SelectedNode.Tag as IOptimizer; Experiment experiment = null; if (optimizerTreeView.SelectedNode.Parent == null) experiment = Content; else experiment = (Experiment)optimizerTreeView.SelectedNode.Parent.Tag; int index = optimizerTreeView.SelectedNode.Index; experiment.Optimizers.Reverse(index, 2); optimizerTreeView.SelectedNode = optimizerTreeViewMapping[optimizer].First(); SetEnabledStateOfControls(); UpdateDetailsViewHost(); RebuildImageList(); } private void removeButton_Click(object sender, EventArgs e) { var treeNode = optimizerTreeView.SelectedNode; var optimizer = (IOptimizer)treeNode.Tag; if (treeNode.Parent == null) Content.Optimizers.Remove(optimizer); else { var batchRun = treeNode.Parent.Tag as BatchRun; var experiment = treeNode.Parent.Tag as Experiment; if (batchRun != null) batchRun.Optimizer = null; else if (experiment != null) experiment.Optimizers.Remove(optimizer); else throw new NotSupportedException("Handling for specific type not implemented" + optimizerTreeView.SelectedNode.Tag.GetType()); } SetEnabledStateOfControls(); UpdateDetailsViewHost(); RebuildImageList(); } private void showDetailsCheckBox_CheckedChanged(object sender, System.EventArgs e) { if (showDetailsCheckBox.Checked) { splitContainer.Panel2Collapsed = false; detailsGroupBox.Enabled = optimizerTreeView.SelectedNode != null; detailsViewHost.Content = optimizerTreeView.SelectedNode != null ? (IOptimizer)optimizerTreeView.SelectedNode.Tag : null; } else { splitContainer.Panel2Collapsed = true; detailsViewHost.Content = null; } } #endregion #region helpers private void UpdateDetailsViewHost() { if (optimizerTreeView.SelectedNode != null) detailsViewHost.Content = (IOptimizer)optimizerTreeView.SelectedNode.Tag; else detailsViewHost.Content = null; } private TreeNode CreateTreeNode(IOptimizer optimizer) { TreeNode node = new TreeNode(optimizer.ToString()); node.Tag = optimizer; List nodes; if (!optimizerTreeViewMapping.TryGetValue(optimizer, out nodes)) { nodes = new List(); optimizerTreeViewMapping.Add(optimizer, nodes); RegisterOptimizerEvents(optimizer); } nodes.Add(node); return node; } private void DisposeTreeNode(TreeNode node) { var optimizer = (IOptimizer)node.Tag; List nodes; if (!optimizerTreeViewMapping.TryGetValue(optimizer, out nodes)) throw new ArgumentException(); nodes.Remove(node); if (nodes.Count == 0) { optimizerTreeViewMapping.Remove(optimizer); DeregisterOptimizerEvents(optimizer); } } private IEnumerable IterateTreeNodes(TreeNode node = null) { TreeNodeCollection nodes; if (node == null) nodes = optimizerTreeView.Nodes; else { nodes = node.Nodes; yield return node; } foreach (var childNode in nodes.OfType()) foreach (var n in IterateTreeNodes(childNode)) yield return n; } private void RebuildImageList() { if (InvokeRequired) { Invoke((Action)RebuildImageList); return; } optimizerTreeView.ImageList.Images.Clear(); foreach (TreeNode treeNode in IterateTreeNodes()) { var optimizer = (IOptimizer)treeNode.Tag; optimizerTreeView.ImageList.Images.Add(optimizer == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : optimizer.ItemImage); treeNode.ImageIndex = optimizerTreeView.ImageList.Images.Count - 1; treeNode.SelectedImageIndex = treeNode.ImageIndex; } } #endregion } }