#region License Information
/* HeuristicLab
* Copyright (C) 2002-2010 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.Generic;
using System.Drawing;
using System.Windows.Forms;
using HeuristicLab.Common.Resources;
using HeuristicLab.Core;
using HeuristicLab.Core.Views;
using HeuristicLab.MainForm;
using HeuristicLab.Persistence.Auxiliary;
namespace HeuristicLab.DebugEngine {
///
/// Base class for editors of engines.
///
[View("DebugEngine View")]
[Content(typeof(DebugEngine), true)]
public partial class DebugEngineView : ItemView {
///
/// Gets or sets the current engine.
///
/// Uses property of base class .
public new DebugEngine Content {
get { return (DebugEngine)base.Content; }
set { base.Content = value; }
}
///
/// Initializes a new instance of .
///
public DebugEngineView() {
InitializeComponent();
updateButton.Image = VS2008ImageLibrary.Refresh;
stepButton.Image = VS2008ImageLibrary.MoveNext;
parentButton.Image = VS2008ImageLibrary.ArrowUp;
}
///
/// Removes the event handlers from the underlying .
///
/// Calls of base class .
protected override void DeregisterContentEvents() {
Content.ExecutionTimeChanged -= new EventHandler(Content_ExecutionTimeChanged);
Content.ExecutionStateChanged -= new EventHandler(Content_ExecutionStateChanged);
base.DeregisterContentEvents();
}
///
/// Adds event handlers to the underlying .
///
/// Calls of base class .
protected override void RegisterContentEvents() {
base.RegisterContentEvents();
Content.ExecutionTimeChanged += new EventHandler(Content_ExecutionTimeChanged);
Content.ExecutionStateChanged += new EventHandler(Content_ExecutionStateChanged);
}
///
/// Updates all controls with the latest data of the model.
///
/// Calls of base class .
protected override void OnContentChanged() {
base.OnContentChanged();
if (Content == null) {
logView.Content = null;
executionTimeTextBox.Text = "-";
} else {
logView.Content = Content.Log;
executionTimeTextBox.Text = Content.ExecutionTime.ToString();
}
}
protected override void SetEnabledStateOfControls() {
base.SetEnabledStateOfControls();
if (Content == null) {
logView.Enabled = false;
executionTimeTextBox.Enabled = false;
} else {
logView.Enabled = true;
executionTimeTextBox.Enabled = true;
}
}
protected virtual void Content_ExecutionTimeChanged(object sender, EventArgs e) {
if (InvokeRequired)
Invoke(new EventHandler(Content_ExecutionTimeChanged), sender, e);
else
executionTimeTextBox.Text = Content == null ? "-" : Content.ExecutionTime.ToString();
}
void Content_ExecutionStateChanged(object sender, EventArgs e) {
switch (Content.ExecutionState) {
case ExecutionState.Paused:
case ExecutionState.Stopped:
case ExecutionState.Prepared:
UpdateView(); break;
}
}
protected virtual void UpdateView() {
if (InvokeRequired) {
Invoke(new Action(UpdateView));
} else {
UpdateExecutionStack();
SetOperation(Content.CurrentOperation);
}
}
private void SetOperation(IOperation operation) {
IAtomicOperation atomicOperation = operation as IAtomicOperation;
operationTextBox.Text = "";
parameterCollectionView.Content = null;
toolTip.SetToolTip(operationTextBox, null);
if (atomicOperation != null && atomicOperation.Operator != null) {
operationTextBox.Text = string.Format("Atomic {0}", atomicOperation.Operator.Name);
toolTip.SetToolTip(operationTextBox, TypeName(atomicOperation.Operator));
}
OperationCollection operationCollection = operation as OperationCollection;
if (operationCollection != null)
operationTextBox.Text = string.Format("Collection {0}", operationCollection.Count);
IExecutionContext context = operation as IExecutionContext;
IScope scope = null;
if (context != null) {
parameterCollectionView.Content = context.Parameters;
scope = context.Scope;
while (scope != null && scope.Parent != null)
scope = scope.Parent;
}
UpdateScope(scope);
if (context != null)
parentButton.Enabled = context.Parent != null;
scopeTreeView.Tag = context;
}
private void UpdateExecutionStack() {
executionStackTreeView.BeginUpdate();
executionStackTreeView.Nodes.Clear();
AddOperations(executionStackTreeView.Nodes, Content.ExecutionStack.ToArray());
executionStackTreeView.ExpandAll();
if (executionStackTreeView.Nodes.Count > 0)
executionStackTreeView.TopNode = executionStackTreeView.Nodes[0];
executionStackTreeView.EndUpdate();
}
private void UpdateScope(IScope scope) {
scopeTreeView.BeginUpdate();
scopeTreeView.Nodes.Clear();
if (scope != null) {
AddScope(scopeTreeView.Nodes, scope);
}
scopeTreeView.ExpandAll();
if (scopeTreeView.Nodes.Count > 0)
scopeTreeView.TopNode = scopeTreeView.Nodes[0];
scopeTreeView.EndUpdate();
}
private string TypeName(object obj) {
if (obj == null)
return "null";
return TypeNameParser.Parse(obj.GetType().ToString()).GetTypeNameInCode(true);
}
private void AddOperations(TreeNodeCollection nodes, IEnumerable operations) {
foreach (IOperation op in operations) {
if (op is IAtomicOperation) {
IAtomicOperation atom = op as IAtomicOperation;
TreeNode node = nodes.Add(atom.Operator.Name);
node.Tag = atom;
node.ToolTipText = TypeName(atom);
node.ImageKey = "AtomicOperation";
if (atom.Operator.Breakpoint)
node.ForeColor = Color.Red;
foreach (var param in atom.Operator.Parameters) {
string typeName = "null";
TreeNode paramNode = node.Nodes.Add(string.Format("Param {0} = {1}", param.Name, GetApproximateValue(param, ref typeName)));
paramNode.Tag = param;
paramNode.ToolTipText = string.Format("{0} = {1}", TypeName(param), typeName);
paramNode.ImageKey = "Parameter";
}
} else if (op is OperationCollection) {
OperationCollection ops = op as OperationCollection;
TreeNode node = executionStackTreeView.Nodes.Add(string.Format("{0} Operations", ops.Count));
node.Tag = op;
node.ToolTipText = TypeName(ops);
node.ImageKey = "OperationCollection";
AddOperations(node.Nodes, ops);
}
}
}
private string GetApproximateValue(IParameter param, ref string typeName) {
string valueString = "";
IExecutionContext context = Content.CurrentOperation as IExecutionContext;
IExecutionContext originalContext = param.ExecutionContext;
object value = null;
try {
try {
param.ExecutionContext = context;
value = param.ActualValue;
} finally {
param.ExecutionContext = originalContext;
}
} catch (Exception) { }
if (value != null) {
valueString = value.ToString();
if (context != originalContext)
valueString = " ~ " + valueString;
typeName = TypeName(value);
}
return valueString;
}
private void AddScope(TreeNodeCollection nodes, IScope scope) {
TreeNode node = nodes.Add(scope.Name);
if (Content.CurrentOperation != null && Content.CurrentOperation.Scope == scope) {
node.ForeColor = Color.Red;
node.BackColor = Color.LightGray;
}
foreach (var var in scope.Variables) {
TreeNode varNode = node.Nodes.Add(string.Format("{0}={1}", var.Name, var.Value.ToString()));
varNode.Tag = var.Value;
varNode.ToolTipText = TypeName(var.Value);
}
foreach (var subScope in scope.SubScopes) {
AddScope(node.Nodes, subScope);
}
}
private void stepButton_Click(object sender, EventArgs e) {
Content.Step();
UpdateView();
}
private void executionStackTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
if (e.Node != null) {
IAtomicOperation op = e.Node.Tag as IAtomicOperation;
if (op != null) {
op.Operator.Breakpoint = !op.Operator.Breakpoint;
if (op.Operator.Breakpoint) {
e.Node.ForeColor = Color.Red;
} else {
e.Node.ForeColor = Color.Black;
}
executionStackTreeView.SelectedNode = null;
}
IParameter param = e.Node.Tag as IParameter;
if (param != null)
MainFormManager.MainForm.ShowContent(param);
}
}
private void updateButton_Click(object sender, EventArgs e) {
UpdateView();
}
private void scopeTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
if (e.Node.Tag != null)
MainFormManager.MainForm.ShowContent((IItem)e.Node.Tag);
}
private void parentButton_Click(object sender, EventArgs e) {
IExecutionContext context = scopeTreeView.Tag as IExecutionContext;
if (context != null) {
SetOperation(context.Parent as IOperation);
}
}
}
}