using System; using System.Collections.Generic; using System.Drawing; using System.Text; using System.Windows.Forms; using HeuristicLab.Common; using HeuristicLab.Common.Resources; using HeuristicLab.Core; using HeuristicLab.MainForm; using HeuristicLab.MainForm.WindowsForms; namespace HeuristicLab.DebugEngine { [View("Operation Content View")] [Content(typeof(OperationContent), IsDefaultView = true)] public sealed partial class OperationContentView : AsynchronousContentView { public new OperationContent Content { get { return (OperationContent)base.Content; } set { base.Content = value; } } public OperationContentView() { InitializeComponent(); } protected override void OnContentChanged() { base.OnContentChanged(); if (Content == null) { nameTextBox.Text = ""; contextLabel.ForeColor = SystemColors.ControlDark; atomicLabel.ForeColor = SystemColors.ControlDark; collectionLabel.ForeColor = SystemColors.ControlDark; parameterListView.Items.Clear(); scopeTreeView.Nodes.Clear(); executionContextTreeView.Nodes.Clear(); } else { contextLabel.ForeColor = Content.IsContext ? Color.Black : SystemColors.ControlDark; atomicLabel.ForeColor = Content.IsAtomic ? Color.Black : SystemColors.ControlDark; collectionLabel.ForeColor = Content.IsCollection ? Color.Black : SystemColors.ControlDark; nameTextBox.Text = Content.Name; UpdateParameters(); UpdateScopeTree(); UpdateExecutionContext(); } } private void UpdateParameters() { parameterListView.BeginUpdate(); parameterListView.Items.Clear(); parameterListView.SmallImageList.Images.Clear(); if (Content.IsAtomic) { foreach (var param in Content.AtomicOperation.Operator.Parameters) { ListViewItem item = parameterListView.Items.Add( string.Format("{0} = {1}", param.Name, GetParameterValue(param, Content.ExecutionContext))); item.Tag = param; parameterListView.SmallImageList.Images.Add(param.ItemImage ?? VS2008ImageLibrary.Nothing); item.ImageIndex = parameterListView.SmallImageList.Images.Count - 1; item.ToolTipText = string.Format("{0}{1}{1}{2}", Utils.TypeName(param), Environment.NewLine, Utils.Wrap(param.Description ?? param.ItemDescription, 60)); } } if (parameterListView.Items.Count > 0) { for (int i = 0; i < parameterListView.Columns.Count; i++) parameterListView.Columns[i].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent); } parameterListView.EndUpdate(); } private object GetParameterValue(IParameter param, IExecutionContext context) { param = (IParameter)param.Clone(); param.ExecutionContext = context; object value = null; try { value = param.ActualValue; } catch (Exception x) { value = x.Message; } return value; } private void UpdateScopeTree() { scopeTreeView.BeginUpdate(); scopeTreeView.Nodes.Clear(); scopeTreeView.ImageList.Images.Clear(); scopeTreeView.ImageList.Images.Add(VS2008ImageLibrary.Namespace); scopeTreeView.ImageList.Images.Add(VS2008ImageLibrary.Field); if (Content.IsContext) { var scope = Content.ExecutionContext.Scope; while (scope != null && scope.Parent != null) scope = scope.Parent; if (scope != null) { AddScope(scopeTreeView.Nodes, scope); } } scopeTreeView.EndUpdate(); } private void AddScope(TreeNodeCollection nodes, IScope scope) { TreeNode node = nodes.Add(string.Format("{0} ({1}+{2})", scope.Name, scope.Variables.Count, scope.SubScopes.Count)); node.Tag = scope; node.ImageIndex = 0; node.SelectedImageIndex = 0; foreach (var var in scope.Variables) { TreeNode varNode = node.Nodes.Add(string.Format("{0}={1}", var.Name, var.Value)); varNode.Tag = var.Value; varNode.ToolTipText = string.Format("{0}{1}{1}{2}", Utils.TypeName(var.Value), Environment.NewLine, Utils.Wrap(var.Description ?? var.ItemDescription, 60)); varNode.ImageIndex = 1; varNode.SelectedImageIndex = 1; } foreach (var subScope in scope.SubScopes) AddScope(node.Nodes, subScope); if (Content.IsAtomic && Content.AtomicOperation.Scope == scope) { node.NodeFont = new Font(DefaultFont, FontStyle.Bold); node.ForeColor = Color.White; node.BackColor = Color.Crimson; node.Expand(); scopeTreeView.TopNode = node; node.ToolTipText = "Current scope of active operation"; } } private void UpdateExecutionContext() { executionContextTreeView.BeginUpdate(); executionContextTreeView.Nodes.Clear(); executionContextTreeView.ImageList.Images.Clear(); executionContextTreeView.ImageList.Images.Add(VS2008ImageLibrary.Namespace); if (Content.IsContext) { AddExecutionContext(Content.ExecutionContext, executionContextTreeView.Nodes); } executionContextTreeView.ExpandAll(); if (executionContextTreeView.Nodes.Count > 0) executionContextTreeView.TopNode = executionContextTreeView.Nodes[0]; executionContextTreeView.EndUpdate(); } private void AddExecutionContext(IExecutionContext executionContext, TreeNodeCollection nodes) { ExecutionContext context = executionContext as ExecutionContext; StringBuilder name = new StringBuilder(); if (context != null && context.Operator != null) name.Append(context.Operator.Name); else name.Append(""); name.Append("@").Append(executionContext.Scope.Name); TreeNode node = nodes.Add(name.ToString()); node.Tag = executionContext; node.ImageIndex = 0; node.SelectedImageIndex = 0; foreach (var param in executionContext.Parameters) { TreeNode paramNode = node.Nodes.Add(string.Format("{0}={1}", param.Name, GetParameterValue(param, executionContext))); paramNode.Tag = param; executionContextTreeView.ImageList.Images.Add(param.ItemImage ?? VS2008ImageLibrary.Nothing); paramNode.ImageIndex = executionContextTreeView.ImageList.Images.Count - 1; paramNode.SelectedImageIndex = paramNode.ImageIndex; paramNode.ToolTipText = string.Format("{0}{1}{1}{2}", Utils.TypeName(param), Environment.NewLine, Utils.Wrap(param.Description ?? param.ItemDescription, 60)); } if (executionContext.Parent != null) AddExecutionContext(executionContext.Parent, node.Nodes); } #region Event Handlers (child controls) private void parameterListView_ItemActivate(object sender, EventArgs e) { if (parameterListView.SelectedItems.Count > 0) { IParameter param = parameterListView.SelectedItems[0].Tag as IParameter; if (param != null) { MainFormManager.MainForm.ShowContent((IContent)GetParameterValue(param, Content.ExecutionContext)); } } } private void executionContextTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node != null) { IParameter param = e.Node.Tag as IParameter; if (param != null) MainFormManager.MainForm.ShowContent(param); } } private void scopeTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node != null) { IItem item = e.Node.Tag as IItem; if (item != null) MainFormManager.MainForm.ShowContent(item); } } private void executionContextTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node != null) { IExecutionContext context = e.Node.Tag as IExecutionContext; if (context != null && context.Scope != null) { TreeNode scopeNode = FindScopeNode(context.Scope, scopeTreeView.Nodes); if (scopeNode != null) { if (timer.Enabled) { timer_Tick(this, EventArgs.Empty); } timer.Tag = new KeyValuePair(scopeNode, new TreeNode() { BackColor = scopeNode.BackColor, ForeColor = scopeNode.ForeColor, NodeFont = scopeNode.NodeFont, }); scopeNode.BackColor = Color.Blue; scopeNode.ForeColor = Color.White; scopeNode.NodeFont = new Font(DefaultFont, FontStyle.Bold); scopeTreeView.TopNode = scopeNode; timer.Start(); } } } } private void ResetNode(TreeNode node, TreeNode template) { if (InvokeRequired) Invoke(new Action(ResetNode), node, template); else { node.ForeColor = template.ForeColor; node.BackColor = template.BackColor; node.NodeFont = template.NodeFont; } } private TreeNode FindScopeNode(IScope scope, TreeNodeCollection nodes) { foreach (TreeNode node in nodes) { if (node.Tag == scope) { return node; } else { TreeNode childNode = FindScopeNode(scope, node.Nodes); if (childNode != null) return childNode; } } return null; } private void timer_Tick(object sender, EventArgs e) { KeyValuePair kvp = (KeyValuePair)timer.Tag; ResetNode(kvp.Key, kvp.Value); timer.Stop(); } private void nameTextBox_DoubleClick(object sender, EventArgs e) { if (Content != null && Content.IsAtomic && Content.AtomicOperation.Operator != null) MainFormManager.MainForm.ShowContent(Content.AtomicOperation.Operator); } #endregion } }