Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
11/30/12 23:15:47 (11 years ago)
Author:
bburlacu
Message:

#1763: Refactored the tree simplifier. Improved tree/node edit operations.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.cs

    r8946 r8980  
    2121
    2222using System;
     23using System.Collections.Generic;
    2324using System.Drawing;
    2425using System.Linq;
     
    2930namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
    3031  public sealed partial class InteractiveSymbolicExpressionTreeChart : SymbolicExpressionTreeChart {
    31     private ISymbolicExpressionTreeNode tempNode;
    32     private VisualSymbolicExpressionTreeNode lastSelected; // previously selected node
     32    private ISymbolicExpressionTreeNode tempNode; // node in clipboard (to be cut/copy/pasted etc)
    3333    private VisualSymbolicExpressionTreeNode currSelected; // currently selected node
    3434    private enum EditOp { NoOp, CopyNode, CopySubtree, CutNode, CutSubtree, DeleteNode, DeleteSubtree }
     
    3737    private TreeState treeState = TreeState.Valid; // tree edit operations must leave the tree in a valid state
    3838
     39    private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> originalNodes; // map a new node to the original node it replaced
     40
    3941    public InteractiveSymbolicExpressionTreeChart() {
    4042      InitializeComponent();
    41       // add extra actions in the context menu strips
    42 
    43 
    44       lastSelected = null;
    4543      currSelected = null;
    4644      tempNode = null;
     45
     46      originalNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();
    4747    }
    4848
     
    6565        Repaint();
    6666      }
     67      foreach (var node in originalNodes.Keys) {
     68        var visualNode = GetVisualSymbolicExpressionTreeNode(node);
     69        if (visualNode == null) continue;
     70        visualNode.LineColor = Color.DodgerBlue;
     71        RepaintNode(visualNode);
     72      }
    6773    }
    6874
    6975    private void contextMenuStrip_Opened(object sender, EventArgs e) {
    70       var menu = sender as ContextMenuStrip;
    71       if (menu == null) return;
     76      var menuStrip = (ContextMenuStrip)sender;
     77      var point = menuStrip.SourceControl.PointToClient(Cursor.Position);
     78      var ea = new MouseEventArgs(MouseButtons.Left, 1, point.X, point.Y, 0);
     79      InteractiveSymbolicExpressionTreeChart_MouseClick(null, ea);
     80
    7281      if (currSelected == null) {
    7382        insertNodeToolStripMenuItem.Visible = false;
    74         changeValueToolStripMenuItem.Visible = false;
     83        editNodeToolStripMenuItem.Visible = false;
    7584        copyToolStripMenuItem.Visible = false;
    7685        cutToolStripMenuItem.Visible = false;
     
    7988      } else {
    8089        var node = currSelected.SymbolicExpressionTreeNode;
    81         changeValueToolStripMenuItem.Visible = (node is SymbolicExpressionTreeTerminalNode);
    82         insertNodeToolStripMenuItem.Visible = !changeValueToolStripMenuItem.Visible;
     90        editNodeToolStripMenuItem.Visible = (node is SymbolicExpressionTreeTerminalNode);
     91        insertNodeToolStripMenuItem.Visible = !editNodeToolStripMenuItem.Visible;
    8392        copyToolStripMenuItem.Visible = true;
    8493        cutToolStripMenuItem.Visible = true;
     
    8998
    9099    protected override void OnSymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
    91       var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
    92       if (visualTreeNode == null || visualTreeNode == currSelected) return;
    93       lastSelected = currSelected;
    94       if (lastSelected != null)
    95         lastSelected.LineColor = Color.Black;
     100      var visualTreeNode = (VisualSymbolicExpressionTreeNode)sender;
     101      var lastSelected = currSelected;
     102      if (lastSelected != null) {
     103        lastSelected.LineColor = originalNodes.ContainsKey(lastSelected.SymbolicExpressionTreeNode) ? Color.DodgerBlue : Color.Black;
     104        RepaintNode(lastSelected);
     105      }
     106
    96107      currSelected = visualTreeNode;
    97       currSelected.LineColor = Color.LightGreen;
    98       Repaint();
    99       base.OnSymbolicExpressionTreeNodeClicked(sender, e);
     108      if (currSelected != null) {
     109        currSelected.LineColor = Color.LightGreen;
     110        RepaintNode(currSelected);
     111      }
     112    }
     113
     114    protected override void OnSymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
     115      var visualTreeNode = (VisualSymbolicExpressionTreeNode)sender;
     116      if (originalNodes.ContainsKey(visualTreeNode.SymbolicExpressionTreeNode)) {
     117        var originalNode = originalNodes[visualTreeNode.SymbolicExpressionTreeNode];
     118
     119        var parent = visualTreeNode.SymbolicExpressionTreeNode.Parent;
     120        var i = parent.IndexOfSubtree(visualTreeNode.SymbolicExpressionTreeNode);
     121        parent.RemoveSubtree(i);
     122        parent.InsertSubtree(i, originalNode);
     123
     124        originalNodes.Remove(visualTreeNode.SymbolicExpressionTreeNode);
     125        visualTreeNode.SymbolicExpressionTreeNode = originalNode;
     126        OnSymbolicExpressionTreeChanged(sender, EventArgs.Empty);
     127      } else {
     128        currSelected = null; // because the tree node will be folded/unfolded
     129        base.OnSymbolicExpressionTreeNodeDoubleClicked(sender, e);
     130        // at this point the tree got redrawn, so we mark the edited nodes
     131        foreach (var node in originalNodes.Keys) {
     132          var visualNode = GetVisualSymbolicExpressionTreeNode(node);
     133          if (visualNode == null) continue;
     134          visualNode.LineColor = Color.DodgerBlue;
     135          RepaintNode(visualNode);
     136        }
     137      }
    100138    }
    101139
    102140    private void insertNodeToolStripMenuItem_Click(object sender, EventArgs e) {
    103141      if (currSelected == null || currSelected.SymbolicExpressionTreeNode is SymbolicExpressionTreeTerminalNode) return;
    104       var node = currSelected.SymbolicExpressionTreeNode;
     142      var parent = currSelected.SymbolicExpressionTreeNode;
    105143
    106144      using (var dialog = new InsertNodeDialog()) {
    107         dialog.SetAllowedSymbols(node.Grammar.AllowedSymbols.Where(s => s.Enabled && s.InitialFrequency > 0.0 && !(s is ProgramRootSymbol || s is StartSymbol || s is Defun)));
    108         dialog.DialogValidated += InsertNodeDialog_Validated;
     145        dialog.SetAllowedSymbols(parent.Grammar.AllowedSymbols.Where(s => s.Enabled && s.InitialFrequency > 0.0 && !(s is ProgramRootSymbol || s is StartSymbol || s is Defun)));
    109146        dialog.ShowDialog(this);
    110       }
    111     }
    112 
    113     private void changeValueToolStripMenuItem_Click(object sender, EventArgs e) {
     147
     148        if (dialog.DialogResult == DialogResult.OK) {
     149          var symbol = dialog.SelectedSymbol();
     150          var node = symbol.CreateTreeNode();
     151          if (node is ConstantTreeNode) {
     152            var constant = node as ConstantTreeNode;
     153            constant.Value = double.Parse(dialog.constantValueTextBox.Text);
     154          } else if (node is VariableTreeNode) {
     155            var variable = node as VariableTreeNode;
     156            variable.Weight = double.Parse(dialog.variableWeightTextBox.Text);
     157            variable.VariableName = dialog.variableNamesCombo.Text;
     158          } else {
     159            if (node.Symbol.MinimumArity <= parent.SubtreeCount && node.Symbol.MaximumArity >= parent.SubtreeCount) {
     160              for (int i = parent.SubtreeCount - 1; i >= 0; --i) {
     161                var child = parent.GetSubtree(i);
     162                parent.RemoveSubtree(i);
     163                node.AddSubtree(child);
     164              }
     165            }
     166          }
     167          if (parent.Symbol.MaximumArity > parent.SubtreeCount) {
     168            parent.AddSubtree(node);
     169            Tree = Tree;
     170          }
     171          OnSymbolicExpressionTreeChanged(sender, e);
     172        }
     173      }
     174    }
     175
     176    private void editNodeToolStripMenuItem_Click(object sender, EventArgs e) {
    114177      if (currSelected == null) return;
    115       var node = currSelected.SymbolicExpressionTreeNode;
    116       using (var dialog = new ValueChangeDialog()) {
    117         dialog.SetContent(node);
    118         dialog.DialogValidated += ChangeValueDialog_Validated;
    119         dialog.ShowDialog(this);
    120       }
    121     }
    122 
    123     public event EventHandler SymbolicExpressionTreeNodeChanged;
    124     private void OnSymbolicExpressionTreeNodeChanged(object sender, EventArgs e) {
    125       var changed = SymbolicExpressionTreeNodeChanged;
    126       if (changed != null)
    127         SymbolicExpressionTreeNodeChanged(sender, e);
    128     }
    129 
    130     private void ChangeValueDialog_Validated(object sender, EventArgs e) {
    131       OnSymbolicExpressionTreeNodeChanged(sender, e);
    132     }
    133 
    134     private void InsertNodeDialog_Validated(object sender, EventArgs e) {
    135       var dialog = (InsertNodeDialog)sender;
    136       var symbol = dialog.SelectedSymbol();
    137       var node = symbol.CreateTreeNode();
    138       var parent = currSelected.SymbolicExpressionTreeNode;
     178
     179      ISymbolicExpressionTreeNode node;
     180      if (originalNodes.ContainsKey(currSelected.SymbolicExpressionTreeNode)) {
     181        node = currSelected.SymbolicExpressionTreeNode;
     182      } else {
     183        node = (ISymbolicExpressionTreeNode)currSelected.SymbolicExpressionTreeNode.Clone();
     184      }
     185      var originalNode = currSelected.SymbolicExpressionTreeNode;
     186      ISymbolicExpressionTreeNode newNode = null;
     187      var result = DialogResult.Cancel;
    139188      if (node is ConstantTreeNode) {
    140         var constant = node as ConstantTreeNode;
    141         constant.Value = double.Parse(dialog.constantValueTextBox.Text);
     189        using (var dialog = new ConstantNodeEditDialog(node)) {
     190          dialog.ShowDialog(this);
     191          newNode = dialog.NewNode;
     192          result = dialog.DialogResult;
     193        }
    142194      } else if (node is VariableTreeNode) {
    143         var variable = node as VariableTreeNode;
    144         variable.Weight = double.Parse(dialog.variableWeightTextBox.Text);
    145         variable.VariableName = dialog.variableNamesCombo.Text;
    146       } else {
    147         if (node.Symbol.MinimumArity <= parent.SubtreeCount && node.Symbol.MaximumArity >= parent.SubtreeCount) {
    148           for (int i = parent.SubtreeCount - 1; i >= 0; --i) {
    149             var child = parent.GetSubtree(i);
    150             parent.RemoveSubtree(i);
    151             node.AddSubtree(child);
    152           }
    153         }
    154       }
    155       if (parent.Symbol.MaximumArity > parent.SubtreeCount) {
    156         parent.AddSubtree(node);
    157         Tree = Tree;
    158       }
    159       OnSymbolicExpressionTreeChanged(sender, e);
     195        using (var dialog = new VariableNodeEditDialog(node)) {
     196          dialog.ShowDialog(this);
     197          newNode = dialog.NewNode;
     198          result = dialog.DialogResult;
     199        }
     200      }
     201      if (result != DialogResult.OK) return;
     202      if (originalNode != newNode) {
     203        var parent = originalNode.Parent;
     204        int i = parent.IndexOfSubtree(originalNode);
     205        parent.RemoveSubtree(i);
     206        parent.InsertSubtree(i, newNode);
     207        originalNodes[newNode] = originalNode;
     208        currSelected.SymbolicExpressionTreeNode = newNode;
     209      }
     210      OnSymbolicExpressionTreeChanged(sender, EventArgs.Empty);
    160211    }
    161212
     
    171222    private void cutSubtreeToolStripMenuItem_Click(object sender, EventArgs e) {
    172223      lastOp = EditOp.CutSubtree;
    173       tempNode = currSelected.SymbolicExpressionTreeNode; // should never be null
     224      tempNode = currSelected.SymbolicExpressionTreeNode;
    174225      foreach (var node in tempNode.IterateNodesPostfix()) {
    175226        var visualNode = GetVisualSymbolicExpressionTreeNode(node);
     
    244295      // check if the copied/cut node (stored in the tempNode) can be inserted as a child of the current selected node
    245296      var node = currSelected.SymbolicExpressionTreeNode;
    246       if (node is ConstantTreeNode || node is VariableTreeNode) return; // nothing to do
     297      if (node is ConstantTreeNode || node is VariableTreeNode) return;
    247298      // check if the currently selected node can accept the copied node as a child
    248299      // no need to check the grammar, an arity check will do just fine here
     
    254305              // arity checks to see if parent can accept node's children (we assume the grammar is already ok with that)
    255306              // (otherise, the 'cut' part of the operation will just not do anything)
    256               if (parent.Symbol.MaximumArity >= tempNode.SubtreeCount + parent.SubtreeCount - 1) {
    257                 // -1 because tempNode will be removed
     307              if (parent.Symbol.MaximumArity >= tempNode.SubtreeCount + parent.SubtreeCount - 1) { // -1 because tempNode will be removed
    258308                parent.RemoveSubtree(parent.IndexOfSubtree(tempNode));
    259309                for (int i = tempNode.SubtreeCount - 1; i >= 0; --i) {
     
    263313                }
    264314                lastOp = EditOp.CopyNode;
    265                 currSelected = null;
    266315              }
    267316              break;
     
    272321              parent.RemoveSubtree(parent.IndexOfSubtree(tempNode));
    273322              lastOp = EditOp.CopySubtree; // do this so the next paste will actually perform a copy   
    274               currSelected = null;
    275323              break;
    276324            }
    277325          case (EditOp.CopyNode): {
    278326              // copy node
    279               var clone = (SymbolicExpressionTreeNode)tempNode.Clone(); // should never be null
     327              var clone = (SymbolicExpressionTreeNode)tempNode.Clone();
    280328              clone.Parent = tempNode.Parent;
    281329              tempNode = clone;
     
    292340        }
    293341        node.AddSubtree(tempNode);
    294         Tree = Tree; // hack in order to trigger the reinitialization of the dictionaries after new nodes appeared in the graph
     342        Tree = Tree; // hack in order to trigger the reinitialization of the dictionaries after new nodes appeared in the tree
    295343        OnSymbolicExpressionTreeChanged(sender, e);
     344        currSelected = null; // because the tree changed and was completely redrawn
    296345      }
    297346    }
     
    305354      return true;
    306355    }
     356
     357    private void InteractiveSymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) {
     358      var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
     359      if (currSelected != null) {
     360        currSelected.LineColor = originalNodes.ContainsKey(currSelected.SymbolicExpressionTreeNode) ? Color.DodgerBlue : Color.Black;
     361      }
     362      currSelected = visualTreeNode;
     363      if (currSelected != null) {
     364        currSelected.LineColor = Color.LightGreen;
     365        RepaintNode(currSelected);
     366      }
     367    }
    307368  }
    308369}
Note: See TracChangeset for help on using the changeset viewer.