#region License Information /* HeuristicLab * Copyright (C) 2002-2014 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.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; using HeuristicLab.Core.Views; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views; using HeuristicLab.EvolutionTracking; using HeuristicLab.EvolutionTracking.Views; using HeuristicLab.MainForm; namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views { [View("SymboldDataAnalysisGenealogyView")] [Content(typeof(IGenealogyGraph), IsDefaultView = true)] public partial class SymboldDataAnalysisGenealogyView : ItemView { private readonly ISymbolicExpressionTreeNodeSimilarityComparer comparer; public SymboldDataAnalysisGenealogyView() { InitializeComponent(); comparer = new SymbolicExpressionTreeNodeSimilarityComparer(); } public new IGenealogyGraph Content { get { return (IGenealogyGraph)base.Content; } set { base.Content = value; } } #region event handlers protected override void OnContentChanged() { base.OnContentChanged(); if (Content != null) { genealogyGraphChart.GenealogyGraph = Content; } } #endregion protected override void RegisterContentEvents() { genealogyGraphChart.GenealogyGraphNodeClicked += graphChart_GenealogyGraphNodeClicked; symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked += treeChart_SymbolicExpressionNodeClicked; base.RegisterContentEvents(); } protected override void DeregisterContentEvents() { base.DeregisterContentEvents(); genealogyGraphChart.GenealogyGraphNodeClicked -= graphChart_GenealogyGraphNodeClicked; symbolicExpressionTreeChart.SymbolicExpressionTreeNodeClicked -= treeChart_SymbolicExpressionNodeClicked; } public void graphChart_GenealogyGraphNodeClicked(object sender, MouseEventArgs args) { var visualNode = (VisualGenealogyGraphNode)sender; var graphNode = (IGenealogyGraphNode)visualNode.Data; var tree = graphNode.Content; symbolicExpressionTreeChart.Tree = tree; if (graphNode.InArcs.Any()) { var fragment = (IFragment)graphNode.InArcs.Last().Data; if (fragment != null) { treeChart_HighlightSubtree(graphNode.Content.NodeAt(fragment.Index1)); } } } public void treeChart_SymbolicExpressionNodeClicked(object sender, MouseEventArgs args) { var visualNode = (VisualTreeNode)sender; var subtree = visualNode.Content; // highlight the selected subtree inside the displayed tree on the right hand side treeChart_ClearColors(); treeChart_HighlightSubtree(subtree); bool trace = genealogyGraphChart.TraceFragments; // check whether the mode is 'trace' or 'match' if (trace) { // perform fragment tracing var graphNode = (IGenealogyGraphNode)genealogyGraphChart.SelectedGraphNode; var subtreeIndex = graphNode.Content.IterateNodesPrefix().ToList().IndexOf(subtree); var fragmentGraph = SymbolicDataAnalysisExpressionTracing.TraceSubtree(graphNode, subtreeIndex); if (fragmentGraph.Nodes.Any()) { MainFormManager.MainForm.ShowContent(fragmentGraph); // display the fragment graph on the screen } } else { // perform matching like it was done before // currently there is no possibility to specify the subtree matching criteria var trees = Content.Nodes.Select(x => x.Content); var matchingTrees = trees.Where(x => x.Root.ContainsSubtree(subtree, comparer)); var matchingVertices = matchingTrees.Select(x => Content[x]).Cast>(); graphChart_highlightMatchingVertices(matchingVertices); } } private void graphChart_highlightMatchingVertices(IEnumerable vertices) { genealogyGraphChart.Chart.UpdateEnabled = false; genealogyGraphChart.ClearPrimitives(); genealogyGraphChart.HighlightNodes(vertices); genealogyGraphChart.Chart.UpdateEnabled = true; genealogyGraphChart.Chart.EnforceUpdate(); } private void treeChart_ClearColors() { foreach (var node in symbolicExpressionTreeChart.Tree.IterateNodesPrefix()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(node); if (visualNode != null) { visualNode.LineColor = Color.Black; visualNode.FillColor = Color.Transparent; } } symbolicExpressionTreeChart.RepaintNodes(); } private void treeChart_HighlightSubtree(ISymbolicExpressionTreeNode subtree) { foreach (var s in subtree.IterateNodesPrefix()) { var visualNode = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNode(s); visualNode.LineColor = Color.RoyalBlue; visualNode.FillColor = Color.LightBlue; foreach (var c in s.Subtrees) { var visualArc = symbolicExpressionTreeChart.GetVisualSymbolicExpressionTreeNodeConnection(s, c); visualArc.LineColor = Color.RoyalBlue; } } symbolicExpressionTreeChart.RepaintNodes(); } #region events for configuring the behavior of the genealogy chart (trace/match, simple lineages, etc) private void trace_checkBox_CheckedChanged(object sender, System.EventArgs e) { genealogyGraphChart.TraceFragments = trace_checkBox.Checked; } private void simpleLineages_checkBox_CheckedChanged(object sender, System.EventArgs e) { genealogyGraphChart.SimpleLineages = simpleLineages_checkBox.Checked; } private void lockGraph_checkBox_CheckedChanged(object sender, System.EventArgs e) { genealogyGraphChart.LockGenealogy = lockGraph_checkBox.Checked; } #endregion } }