Changeset 9006
- Timestamp:
- 12/06/12 13:52:01 (12 years ago)
- Location:
- trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.Designer.cs
r8980 r9006 52 52 this.btnSimplify = new System.Windows.Forms.Button(); 53 53 this.btnOptimizeConstants = new System.Windows.Forms.Button(); 54 this.grpViewHost = new System.Windows.Forms.GroupBox(); 55 this.treeStatusLabel = new System.Windows.Forms.Label(); 56 this.treeStatusValue = new System.Windows.Forms.Label(); 54 57 this.treeChart = new HeuristicLab.Problems.DataAnalysis.Symbolic.Views.InteractiveSymbolicExpressionTreeChart(); 55 this.grpViewHost = new System.Windows.Forms.GroupBox();56 58 ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); 57 59 this.splitContainer.Panel1.SuspendLayout(); … … 74 76 this.viewHost.Name = "viewHost"; 75 77 this.viewHost.ReadOnly = false; 76 this.viewHost.Size = new System.Drawing.Size(33 5, 326);78 this.viewHost.Size = new System.Drawing.Size(336, 383); 77 79 this.viewHost.TabIndex = 0; 78 80 this.viewHost.ViewsLabelVisible = true; … … 92 94 // 93 95 this.splitContainer.Panel2.Controls.Add(this.grpViewHost); 94 this.splitContainer.Size = new System.Drawing.Size(56 4, 348);96 this.splitContainer.Size = new System.Drawing.Size(565, 405); 95 97 this.splitContainer.SplitterDistance = 213; 96 98 this.splitContainer.TabIndex = 1; … … 99 101 // 100 102 this.grpSimplify.AutoSize = true; 103 this.grpSimplify.Controls.Add(this.treeStatusValue); 101 104 this.grpSimplify.Controls.Add(this.flowLayoutPanel); 105 this.grpSimplify.Controls.Add(this.treeStatusLabel); 102 106 this.grpSimplify.Controls.Add(this.treeChart); 103 107 this.grpSimplify.Dock = System.Windows.Forms.DockStyle.Fill; 104 108 this.grpSimplify.Location = new System.Drawing.Point(0, 0); 105 109 this.grpSimplify.Name = "grpSimplify"; 106 this.grpSimplify.Size = new System.Drawing.Size(213, 348);110 this.grpSimplify.Size = new System.Drawing.Size(213, 405); 107 111 this.grpSimplify.TabIndex = 1; 108 112 this.grpSimplify.TabStop = false; … … 113 117 this.flowLayoutPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 114 118 | System.Windows.Forms.AnchorStyles.Right))); 119 this.flowLayoutPanel.Controls.Add(this.btnOptimizeConstants); 115 120 this.flowLayoutPanel.Controls.Add(this.btnSimplify); 116 this.flowLayoutPanel.Controls.Add(this.btnOptimizeConstants); 117 this.flowLayoutPanel.Location = new System.Drawing.Point(6, 313); 121 this.flowLayoutPanel.Location = new System.Drawing.Point(6, 370); 118 122 this.flowLayoutPanel.Name = "flowLayoutPanel"; 119 123 this.flowLayoutPanel.Size = new System.Drawing.Size(204, 29); … … 123 127 // btnSimplify 124 128 // 125 this.btnSimplify.Location = new System.Drawing.Point( 3, 3);129 this.btnSimplify.Location = new System.Drawing.Point(106, 3); 126 130 this.btnSimplify.Name = "btnSimplify"; 127 131 this.btnSimplify.Size = new System.Drawing.Size(95, 23); … … 135 139 this.btnOptimizeConstants.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 136 140 this.btnOptimizeConstants.Enabled = false; 137 this.btnOptimizeConstants.Location = new System.Drawing.Point( 104, 3);141 this.btnOptimizeConstants.Location = new System.Drawing.Point(3, 3); 138 142 this.btnOptimizeConstants.Name = "btnOptimizeConstants"; 139 143 this.btnOptimizeConstants.Size = new System.Drawing.Size(97, 23); … … 143 147 this.btnOptimizeConstants.Click += new System.EventHandler(this.btnOptimizeConstants_Click); 144 148 // 149 // grpViewHost 150 // 151 this.grpViewHost.Controls.Add(this.viewHost); 152 this.grpViewHost.Dock = System.Windows.Forms.DockStyle.Fill; 153 this.grpViewHost.Location = new System.Drawing.Point(0, 0); 154 this.grpViewHost.Name = "grpViewHost"; 155 this.grpViewHost.Size = new System.Drawing.Size(348, 405); 156 this.grpViewHost.TabIndex = 1; 157 this.grpViewHost.TabStop = false; 158 this.grpViewHost.Text = "Details"; 159 // 160 // treeStatusLabel 161 // 162 this.treeStatusLabel.AutoSize = true; 163 this.treeStatusLabel.BackColor = System.Drawing.Color.Transparent; 164 this.treeStatusLabel.Location = new System.Drawing.Point(6, 16); 165 this.treeStatusLabel.Name = "treeStatusLabel"; 166 this.treeStatusLabel.Size = new System.Drawing.Size(68, 13); 167 this.treeStatusLabel.TabIndex = 2; 168 this.treeStatusLabel.Text = "Tree Status: "; 169 // 170 // treeStatusValue 171 // 172 this.treeStatusValue.AutoSize = true; 173 this.treeStatusValue.BackColor = System.Drawing.Color.Transparent; 174 this.treeStatusValue.ForeColor = System.Drawing.Color.Green; 175 this.treeStatusValue.Location = new System.Drawing.Point(72, 16); 176 this.treeStatusValue.Name = "treeStatusValue"; 177 this.treeStatusValue.Size = new System.Drawing.Size(30, 13); 178 this.treeStatusValue.TabIndex = 3; 179 this.treeStatusValue.Text = "Valid"; 180 // 145 181 // treeChart 146 182 // … … 150 186 this.treeChart.BackgroundColor = System.Drawing.Color.White; 151 187 this.treeChart.LineColor = System.Drawing.Color.Black; 152 this.treeChart.Location = new System.Drawing.Point(6, 16); 188 this.treeChart.Location = new System.Drawing.Point(6, 32); 189 this.treeChart.ModifyTree = null; 153 190 this.treeChart.Name = "treeChart"; 154 this.treeChart.Size = new System.Drawing.Size(201, 291);191 this.treeChart.Size = new System.Drawing.Size(201, 332); 155 192 this.treeChart.Spacing = 5; 156 193 this.treeChart.SuspendRepaint = false; … … 158 195 this.treeChart.TextFont = new System.Drawing.Font("Times New Roman", 8F); 159 196 this.treeChart.Tree = null; 160 this.treeChart.SymbolicExpressionTree Changed += new System.EventHandler(this.treeChart_SymbolicExpressionTreeChanged);197 this.treeChart.SymbolicExpressionTreeNodeClicked += new System.Windows.Forms.MouseEventHandler(this.treeChart_SymbolicExpressionTreeNodeClicked); 161 198 this.treeChart.SymbolicExpressionTreeNodeDoubleClicked += new System.Windows.Forms.MouseEventHandler(this.treeChart_SymbolicExpressionTreeNodeDoubleClicked); 162 //163 // grpViewHost164 //165 this.grpViewHost.Controls.Add(this.viewHost);166 this.grpViewHost.Dock = System.Windows.Forms.DockStyle.Fill;167 this.grpViewHost.Location = new System.Drawing.Point(0, 0);168 this.grpViewHost.Name = "grpViewHost";169 this.grpViewHost.Size = new System.Drawing.Size(347, 348);170 this.grpViewHost.TabIndex = 1;171 this.grpViewHost.TabStop = false;172 this.grpViewHost.Text = "Details";173 199 // 174 200 // InteractiveSymbolicDataAnalysisSolutionSimplifierView … … 179 205 this.DoubleBuffered = true; 180 206 this.Name = "InteractiveSymbolicDataAnalysisSolutionSimplifierView"; 181 this.Size = new System.Drawing.Size(56 4, 348);207 this.Size = new System.Drawing.Size(565, 405); 182 208 this.splitContainer.Panel1.ResumeLayout(false); 183 209 this.splitContainer.Panel1.PerformLayout(); … … 186 212 this.splitContainer.ResumeLayout(false); 187 213 this.grpSimplify.ResumeLayout(false); 214 this.grpSimplify.PerformLayout(); 188 215 this.flowLayoutPanel.ResumeLayout(false); 189 216 this.grpViewHost.ResumeLayout(false); 190 217 this.ResumeLayout(false); 218 191 219 } 192 220 … … 201 229 private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel; 202 230 protected System.Windows.Forms.Button btnOptimizeConstants; 231 private System.Windows.Forms.Label treeStatusValue; 232 private System.Windows.Forms.Label treeStatusLabel; 203 233 } 204 234 } -
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicDataAnalysisSolutionSimplifierView.cs
r8990 r9006 32 32 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views { 33 33 public abstract partial class InteractiveSymbolicDataAnalysisSolutionSimplifierView : AsynchronousContentView { 34 private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> replacementNodes; 34 private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> foldedNodes; 35 private Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> changedNodes; 35 36 private Dictionary<ISymbolicExpressionTreeNode, double> nodeImpacts; 37 private enum TreeState { Valid, Invalid } 38 private TreeState treeState; 36 39 37 40 public InteractiveSymbolicDataAnalysisSolutionSimplifierView() { 38 41 InitializeComponent(); 39 replacementNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); 42 foldedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); 43 changedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); 40 44 nodeImpacts = new Dictionary<ISymbolicExpressionTreeNode, double>(); 41 45 this.Caption = "Interactive Solution Simplifier"; 46 47 // initialize the tree modifier that will be used to perform edit operations over the tree 48 treeChart.ModifyTree = Modify; 49 } 50 51 /// <summary> 52 /// Remove, Replace or Insert subtrees 53 /// </summary> 54 /// <param name="tree">The symbolic expression tree</param> 55 /// <param name="node">The insertion point (the parent node who will receive a new child)</param> 56 /// <param name="oldChild">The subtree to be replaced</param> 57 /// <param name="newChild">The replacement subtree</param> 58 /// <param name="removeSubtree">Flag used to indicate if whole subtrees should be removed (default behavior), or just the subtree root</param> 59 private void Modify(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode node, ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild, 60 bool removeSubtree = true) { 61 if (oldChild == null && newChild == null) throw new ArgumentException(); 62 if (oldChild == null) { // insertion operation 63 node.AddSubtree(newChild); 64 newChild.Parent = node; 65 treeChart.Tree = tree; // because a new node is present in the tree, the visualNodes dictionary needs to be updated 66 } else if (newChild == null) { // removal operation 67 // use switch instead of if/else purely for aesthetical reasons (to avoid nested ifs and elses) 68 switch (removeSubtree) { 69 case true: 70 // remove the whole subtree 71 node.RemoveSubtree(node.IndexOfSubtree(oldChild)); 72 if (oldChild.SubtreeCount > 0) 73 foreach (var subtree in oldChild.IterateNodesBreadth()) { 74 changedNodes.Remove(subtree); 75 foldedNodes.Remove(subtree); 76 } 77 break; 78 case false: 79 // only remove the current node and try to preserve its subtrees 80 node.RemoveSubtree(node.IndexOfSubtree(oldChild)); 81 if (oldChild.SubtreeCount > 0) 82 for (int i = oldChild.SubtreeCount - 1; i >= 0; --i) { 83 var subtree = oldChild.GetSubtree(i); 84 oldChild.RemoveSubtree(i); 85 node.AddSubtree(subtree); 86 } 87 break; 88 } 89 changedNodes.Remove(oldChild); 90 foldedNodes.Remove(oldChild); 91 } else { // replacement operation 92 var replacementIndex = node.IndexOfSubtree(oldChild); 93 node.RemoveSubtree(replacementIndex); 94 node.InsertSubtree(replacementIndex, newChild); 95 newChild.Parent = node; 96 if (changedNodes.ContainsKey(oldChild)) { 97 changedNodes.Add(newChild, changedNodes[oldChild]); // so that on double click the original node is restored 98 changedNodes.Remove(oldChild); 99 } else { 100 changedNodes.Add(newChild, oldChild); 101 } 102 } 103 104 if (IsValid(tree)) { 105 treeState = TreeState.Valid; 106 UpdateModel(Content.Model.SymbolicExpressionTree); 107 btnOptimizeConstants.Enabled = true; 108 btnSimplify.Enabled = true; 109 treeStatusValue.Text = "Valid"; 110 treeStatusValue.ForeColor = Color.Green; 111 this.Refresh(); 112 } else { 113 treeState = TreeState.Invalid; 114 btnOptimizeConstants.Enabled = true; 115 btnSimplify.Enabled = true; 116 treeStatusValue.Text = "Invalid"; 117 treeStatusValue.ForeColor = Color.Red; 118 treeChart.Repaint(); 119 this.Refresh(); 120 } 121 foreach (var changedNode in changedNodes.Keys) { 122 var visualNode = treeChart.GetVisualSymbolicExpressionTreeNode(changedNode); 123 visualNode.LineColor = Color.DodgerBlue; 124 treeChart.RepaintNode(visualNode); 125 } 126 } 127 128 private static bool IsValid(ISymbolicExpressionTree tree) { 129 return !tree.IterateNodesPostfix().Any(node => node.SubtreeCount < node.Symbol.MinimumArity || node.SubtreeCount > node.Symbol.MaximumArity); 42 130 } 43 131 … … 64 152 protected override void OnContentChanged() { 65 153 base.OnContentChanged(); 66 replacementNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); 67 154 foldedNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(); 68 155 UpdateView(); 69 156 viewHost.Content = this.Content; … … 77 164 var replacementValues = CalculateReplacementValues(tree); 78 165 foreach (var pair in replacementValues.Where(pair => !(pair.Key is ConstantTreeNode))) { 79 replacementNodes[pair.Key] = MakeConstantTreeNode(pair.Value);166 foldedNodes[pair.Key] = MakeConstantTreeNode(pair.Value); 80 167 } 81 168 … … 95 182 } 96 183 184 private void treeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) { 185 var visualNode = (VisualSymbolicExpressionTreeNode)sender; 186 if (visualNode == null) return; 187 var treeNode = visualNode.SymbolicExpressionTreeNode; 188 if (changedNodes.ContainsKey(treeNode)) { 189 visualNode.LineColor = Color.DodgerBlue; 190 } else if (treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) { 191 visualNode.LineColor = Color.DarkOrange; 192 } else { 193 visualNode.LineColor = Color.Black; 194 } 195 visualNode.TextColor = Color.Black; 196 treeChart.RepaintNode(visualNode); 197 } 198 97 199 private void treeChart_SymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) { 98 if ( !treeChart.TreeValid) return;200 if (treeState == TreeState.Invalid) return; 99 201 var visualNode = (VisualSymbolicExpressionTreeNode)sender; 100 202 var symbExprTreeNode = (SymbolicExpressionTreeNode)visualNode.SymbolicExpressionTreeNode; 101 203 if (symbExprTreeNode == null) return; 102 if (!replacementNodes.ContainsKey(symbExprTreeNode)) return;103 104 204 var tree = Content.Model.SymbolicExpressionTree; 105 int indexOfReplacementNode = symbExprTreeNode.Parent.IndexOfSubtree(symbExprTreeNode); 106 SwitchNodeWithReplacementNode(symbExprTreeNode.Parent, indexOfReplacementNode); 107 UpdateModel(tree); 108 } 109 110 private void treeChart_SymbolicExpressionTreeChanged(object sender, EventArgs e) { 111 UpdateModel(Content.Model.SymbolicExpressionTree); 205 var parent = symbExprTreeNode.Parent; 206 int indexOfSubtree = parent.IndexOfSubtree(symbExprTreeNode); 207 if (changedNodes.ContainsKey(symbExprTreeNode)) { 208 parent.RemoveSubtree(indexOfSubtree); 209 ISymbolicExpressionTreeNode originalNode = changedNodes[symbExprTreeNode]; 210 parent.InsertSubtree(indexOfSubtree, originalNode); 211 changedNodes.Remove(symbExprTreeNode); 212 UpdateModel(tree); 213 } else if (foldedNodes.ContainsKey(symbExprTreeNode)) { 214 SwitchNodeWithReplacementNode(parent, indexOfSubtree); 215 UpdateModel(tree); 216 } 112 217 } 113 218 … … 115 220 ISymbolicExpressionTreeNode subTree = parent.GetSubtree(subTreeIndex); 116 221 parent.RemoveSubtree(subTreeIndex); 117 if ( replacementNodes.ContainsKey(subTree)) {118 var replacementNode = replacementNodes[subTree];222 if (foldedNodes.ContainsKey(subTree)) { 223 var replacementNode = foldedNodes[subTree]; 119 224 parent.InsertSubtree(subTreeIndex, replacementNode); 120 225 // exchange key and value 121 replacementNodes.Remove(subTree);122 replacementNodes.Add(replacementNode, subTree);226 foldedNodes.Remove(subTree); 227 foldedNodes.Add(replacementNode, subTree); 123 228 } 124 229 } … … 147 252 } 148 253 visualTree.ToolTip += Environment.NewLine + "Node impact: " + impact; 149 var constantReplacementNode = replacementNodes[treeNode] as ConstantTreeNode;254 var constantReplacementNode = foldedNodes[treeNode] as ConstantTreeNode; 150 255 if (constantReplacementNode != null) { 151 256 visualTree.ToolTip += Environment.NewLine + "Replacement value: " + constantReplacementNode.Value; 152 257 } 153 258 } 154 if (visualTree != null && treeNode is ConstantTreeNode && replacementNodes.ContainsKey(treeNode)) {259 if (visualTree != null && treeNode is ConstantTreeNode && foldedNodes.ContainsKey(treeNode)) { 155 260 visualTree.LineColor = Color.DarkOrange; 156 261 } -
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.Designer.cs
r8991 r9006 54 54 this.removeSubtreeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 55 55 this.pasteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 56 this.treeStatusLabel = new System.Windows.Forms.Label();57 this.treeStatusValue = new System.Windows.Forms.Label();58 56 this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator(); 59 57 this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); … … 63 61 // 64 62 this.insertNodeToolStripMenuItem.Name = "insertNodeToolStripMenuItem"; 65 this.insertNodeToolStripMenuItem.Size = new System.Drawing.Size(1 52, 22);63 this.insertNodeToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 66 64 this.insertNodeToolStripMenuItem.Text = "Insert Node"; 67 65 this.insertNodeToolStripMenuItem.Click += new System.EventHandler(this.insertNodeToolStripMenuItem_Click); … … 69 67 // changeNodeToolStripMenuItem 70 68 // 71 this.changeNodeToolStripMenuItem.Name = " editNodeToolStripMenuItem";72 this.changeNodeToolStripMenuItem.Size = new System.Drawing.Size(1 52, 22);69 this.changeNodeToolStripMenuItem.Name = "changeNodeToolStripMenuItem"; 70 this.changeNodeToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 73 71 this.changeNodeToolStripMenuItem.Text = "Change Node"; 74 72 this.changeNodeToolStripMenuItem.Click += new System.EventHandler(this.changeNodeToolStripMenuItem_Click); 75 //76 // copyToolStripMenuItem77 //78 this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";79 this.copyToolStripMenuItem.Size = new System.Drawing.Size(152, 22);80 this.copyToolStripMenuItem.Text = "Copy";81 this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);82 73 // 83 74 // cutToolStripMenuItem 84 75 // 85 76 this.cutToolStripMenuItem.Name = "cutToolStripMenuItem"; 86 this.cutToolStripMenuItem.Size = new System.Drawing.Size(1 52, 22);77 this.cutToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 87 78 this.cutToolStripMenuItem.Text = "Cut"; 88 79 this.cutToolStripMenuItem.Click += new System.EventHandler(this.cutToolStripMenuItem_Click); … … 94 85 this.removeSubtreeToolStripMenuItem}); 95 86 this.removeToolStripMenuItem.Name = "removeToolStripMenuItem"; 96 this.removeToolStripMenuItem.Size = new System.Drawing.Size(1 52, 22);87 this.removeToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 97 88 this.removeToolStripMenuItem.Text = "Remove"; 98 89 this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeSubtreeToolStripMenuItem_Click); … … 101 92 // 102 93 this.removeNodeToolStripMenuItem.Name = "removeNodeToolStripMenuItem"; 103 this.removeNodeToolStripMenuItem.Size = new System.Drawing.Size(1 52, 22);94 this.removeNodeToolStripMenuItem.Size = new System.Drawing.Size(114, 22); 104 95 this.removeNodeToolStripMenuItem.Text = "Node"; 105 96 this.removeNodeToolStripMenuItem.Click += new System.EventHandler(this.removeNodeToolStripMenuItem_Click); … … 108 99 // 109 100 this.removeSubtreeToolStripMenuItem.Name = "removeSubtreeToolStripMenuItem"; 110 this.removeSubtreeToolStripMenuItem.Size = new System.Drawing.Size(1 52, 22);101 this.removeSubtreeToolStripMenuItem.Size = new System.Drawing.Size(114, 22); 111 102 this.removeSubtreeToolStripMenuItem.Text = "Subtree"; 112 103 this.removeSubtreeToolStripMenuItem.Click += new System.EventHandler(this.removeSubtreeToolStripMenuItem_Click); … … 115 106 // 116 107 this.pasteToolStripMenuItem.Name = "pasteToolStripMenuItem"; 117 this.pasteToolStripMenuItem.Size = new System.Drawing.Size(1 52, 22);108 this.pasteToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 118 109 this.pasteToolStripMenuItem.Text = "Paste"; 119 110 this.pasteToolStripMenuItem.Click += new System.EventHandler(this.pasteToolStripMenuItem_Clicked); 120 //121 // contextMenuStrip122 //123 this.contextMenuStrip.Opened += this.contextMenuStrip_Opened;124 this.contextMenuStrip.Items.AddRange(new ToolStripItem[] { insertNodeToolStripMenuItem,125 changeNodeToolStripMenuItem,126 copyToolStripMenuItem,127 cutToolStripMenuItem,128 removeToolStripMenuItem,129 pasteToolStripMenuItem });130 //131 // treeStatusLabel132 //133 this.treeStatusLabel.AutoSize = true;134 this.treeStatusLabel.BackColor = System.Drawing.Color.Transparent;135 this.treeStatusLabel.Location = new System.Drawing.Point(3, 0);136 this.treeStatusLabel.Name = "treeStatusLabel";137 this.treeStatusLabel.Size = new System.Drawing.Size(68, 13);138 this.treeStatusLabel.TabIndex = 0;139 this.treeStatusLabel.Text = "Tree Status: ";140 //141 // treeStatusValue142 //143 this.treeStatusValue.AutoSize = true;144 this.treeStatusValue.BackColor = System.Drawing.Color.Transparent;145 this.treeStatusValue.ForeColor = System.Drawing.Color.Green;146 this.treeStatusValue.Location = new System.Drawing.Point(77, 0);147 this.treeStatusValue.Name = "treeStatusValue";148 this.treeStatusValue.Size = new System.Drawing.Size(30, 13);149 this.treeStatusValue.TabIndex = 1;150 this.treeStatusValue.Text = "Valid";151 111 // 152 112 // toolStripSeparator … … 155 115 this.toolStripSeparator.Size = new System.Drawing.Size(149, 6); 156 116 // 117 // copyToolStripMenuItem 118 // 119 this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; 120 this.copyToolStripMenuItem.Size = new System.Drawing.Size(147, 22); 121 this.copyToolStripMenuItem.Text = "Copy"; 122 this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click); 123 // 124 // contextMenuStrip 125 // 126 this.contextMenuStrip.Opened += this.contextMenuStrip_Opened; 127 this.contextMenuStrip.Items.AddRange(new ToolStripItem[] { insertNodeToolStripMenuItem, 128 changeNodeToolStripMenuItem, 129 copyToolStripMenuItem, 130 cutToolStripMenuItem, 131 removeToolStripMenuItem, 132 pasteToolStripMenuItem }); 133 // 157 134 // InteractiveSymbolicExpressionTreeChart 158 135 // 159 136 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 160 137 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 161 this.Controls.Add(this.treeStatusLabel);162 this.Controls.Add(this.treeStatusValue);163 138 this.DoubleBuffered = true; 164 139 this.Name = "InteractiveSymbolicExpressionTreeChart"; 165 this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.InteractiveSymbolicExpressionTreeChart_MouseClick);166 140 this.ResumeLayout(false); 167 this.PerformLayout();168 141 169 142 } … … 178 151 179 152 #endregion 180 private Label treeStatusLabel; 181 private Label treeStatusValue; 153 182 154 private ToolStripSeparator toolStripSeparator; 183 155 private ToolStripMenuItem copyToolStripMenuItem; -
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/InteractiveSymbolicExpressionTreeChart.cs
r8991 r9006 21 21 22 22 using System; 23 using System.Collections.Generic;24 23 using System.Drawing; 25 24 using System.Linq; … … 29 28 30 29 namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views { 31 public sealed partial class InteractiveSymbolicExpressionTreeChart : SymbolicExpressionTreeChart { 30 internal delegate void 31 ModifyTree(ISymbolicExpressionTree tree, ISymbolicExpressionTreeNode node, ISymbolicExpressionTreeNode oldChild, ISymbolicExpressionTreeNode newChild, 32 bool removeSubtree = true); 33 34 internal sealed partial class InteractiveSymbolicExpressionTreeChart : SymbolicExpressionTreeChart { 32 35 private ISymbolicExpressionTreeNode tempNode; // node in clipboard (to be cut/copy/pasted etc) 33 36 private VisualSymbolicExpressionTreeNode currSelected; // currently selected node 34 private enum EditOp { NoOp, CopyNode, CopySubtree, CutNode, CutSubtree, RemoveNode, RemoveSubtree } 35 private enum TreeState { Valid, Invalid } 37 public enum EditOp { NoOp, CopySubtree, CutSubtree, ChangeNode, InsertNode, InsertSubtree, RemoveNode, RemoveSubtree } 36 38 private EditOp lastOp = EditOp.NoOp; 37 private TreeState treeState = TreeState.Valid; // tree edit operations must leave the tree in a valid state 38 39 p rivate Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode> originalNodes; // map a new node to the original node it replaced39 40 // delegate to notify the parent container (the view) about the tree edit operations that it needs to perform 41 public ModifyTree ModifyTree { get; set; } 40 42 41 43 public InteractiveSymbolicExpressionTreeChart() { … … 43 45 currSelected = null; 44 46 tempNode = null; 45 46 originalNodes = new Dictionary<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>();47 }48 49 public bool TreeValid { get { return TreeState.Valid == treeState; } }50 // expose an additional event for signaling to the parent view when the tree structure was modified51 // the emitting of the signal is conditional on the tree being valid, otherwise only a Repaint is issued52 public event EventHandler SymbolicExpressionTreeChanged;53 private void OnSymbolicExpressionTreeChanged(object sender, EventArgs e) {54 if (IsValid(Tree)) {55 treeStatusValue.Text = "Valid";56 treeStatusValue.ForeColor = Color.Green;57 treeState = TreeState.Valid;58 var changed = SymbolicExpressionTreeChanged;59 if (changed != null)60 changed(sender, e);61 } else {62 treeStatusValue.Text = "Invalid";63 treeStatusValue.ForeColor = Color.Red;64 treeState = TreeState.Invalid;65 Tree = Tree; // reinitialize the dictionaries and repaint66 }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 }73 47 } 74 48 … … 77 51 var point = menuStrip.SourceControl.PointToClient(Cursor.Position); 78 52 var ea = new MouseEventArgs(MouseButtons.Left, 1, point.X, point.Y, 0); 79 InteractiveSymbolicExpressionTreeChart_MouseClick(null, ea); 53 var visualNode = FindVisualSymbolicExpressionTreeNodeAt(ea.X, ea.Y); 54 if (visualNode != null) { OnSymbolicExpressionTreeNodeClicked(visualNode, ea); }; 80 55 81 56 if (currSelected == null) { … … 103 78 var visualTreeNode = (VisualSymbolicExpressionTreeNode)sender; 104 79 var lastSelected = currSelected; 105 if (lastSelected != null) {106 lastSelected.LineColor = originalNodes.ContainsKey(lastSelected.SymbolicExpressionTreeNode) ? Color.DodgerBlue : Color.Black;107 RepaintNode(lastSelected);108 }109 110 80 currSelected = visualTreeNode; 111 81 if (currSelected != null) { … … 113 83 RepaintNode(currSelected); 114 84 } 85 if (lastSelected != null) 86 base.OnSymbolicExpressionTreeNodeClicked(lastSelected, e); 115 87 } 116 88 117 89 protected override void OnSymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) { 118 var visualTreeNode = (VisualSymbolicExpressionTreeNode)sender; 119 if (originalNodes.ContainsKey(visualTreeNode.SymbolicExpressionTreeNode)) { 120 var originalNode = originalNodes[visualTreeNode.SymbolicExpressionTreeNode]; 121 122 var parent = visualTreeNode.SymbolicExpressionTreeNode.Parent; 123 var i = parent.IndexOfSubtree(visualTreeNode.SymbolicExpressionTreeNode); 124 parent.RemoveSubtree(i); 125 parent.InsertSubtree(i, originalNode); 126 127 originalNodes.Remove(visualTreeNode.SymbolicExpressionTreeNode); 128 visualTreeNode.SymbolicExpressionTreeNode = originalNode; 129 OnSymbolicExpressionTreeChanged(sender, EventArgs.Empty); 130 } else { 131 currSelected = null; // because the tree node will be folded/unfolded 132 base.OnSymbolicExpressionTreeNodeDoubleClicked(sender, e); 133 // at this point the tree got redrawn, so we mark the edited nodes 134 foreach (var node in originalNodes.Keys) { 135 var visualNode = GetVisualSymbolicExpressionTreeNode(node); 136 if (visualNode == null) continue; 137 visualNode.LineColor = Color.DodgerBlue; 138 RepaintNode(visualNode); 139 } 140 } 90 currSelected = null; 91 base.OnSymbolicExpressionTreeNodeDoubleClicked(sender, e); 141 92 } 142 93 … … 148 99 dialog.SetAllowedSymbols(parent.Grammar.AllowedSymbols.Where(s => s.Enabled && s.InitialFrequency > 0.0 && !(s is ProgramRootSymbol || s is StartSymbol || s is Defun))); 149 100 dialog.ShowDialog(this); 150 151 if (dialog.DialogResult == DialogResult.OK) { 152 var symbol = dialog.SelectedSymbol(); 153 var node = symbol.CreateTreeNode(); 154 if (node is ConstantTreeNode) { 155 var constant = node as ConstantTreeNode; 156 constant.Value = double.Parse(dialog.constantValueTextBox.Text); 157 } else if (node is VariableTreeNode) { 158 var variable = node as VariableTreeNode; 159 variable.Weight = double.Parse(dialog.variableWeightTextBox.Text); 160 variable.VariableName = dialog.variableNamesCombo.Text; 161 } else { 162 if (node.Symbol.MinimumArity <= parent.SubtreeCount && node.Symbol.MaximumArity >= parent.SubtreeCount) { 163 for (int i = parent.SubtreeCount - 1; i >= 0; --i) { 164 var child = parent.GetSubtree(i); 165 parent.RemoveSubtree(i); 166 node.AddSubtree(child); 167 } 168 } 169 } 170 if (parent.Symbol.MaximumArity > parent.SubtreeCount) { 171 parent.AddSubtree(node); 172 Tree = Tree; 173 } 174 OnSymbolicExpressionTreeChanged(sender, e); 175 currSelected = null; 176 } 177 } 101 if (dialog.DialogResult != DialogResult.OK) return; 102 103 var symbol = dialog.SelectedSymbol(); 104 var node = symbol.CreateTreeNode(); 105 if (node is ConstantTreeNode) { 106 var constant = node as ConstantTreeNode; 107 constant.Value = double.Parse(dialog.constantValueTextBox.Text); 108 } else if (node is VariableTreeNode) { 109 var variable = node as VariableTreeNode; 110 variable.Weight = double.Parse(dialog.variableWeightTextBox.Text); 111 variable.VariableName = dialog.variableNamesCombo.Text; 112 } else if (node.Symbol.MinimumArity <= parent.SubtreeCount && node.Symbol.MaximumArity >= parent.SubtreeCount) { 113 for (int i = parent.SubtreeCount - 1; i >= 0; --i) { 114 var child = parent.GetSubtree(i); 115 parent.RemoveSubtree(i); 116 node.AddSubtree(child); 117 } 118 } 119 // the if condition will always be true for the final else clause above 120 if (parent.Symbol.MaximumArity > parent.SubtreeCount) { 121 ModifyTree(Tree, parent, null, node); 122 } 123 } 124 currSelected = null; 178 125 } 179 126 … … 181 128 if (currSelected == null) return; 182 129 183 ISymbolicExpressionTreeNode node; 184 if (originalNodes.ContainsKey(currSelected.SymbolicExpressionTreeNode)) { 185 node = currSelected.SymbolicExpressionTreeNode; 186 } else { 187 node = (ISymbolicExpressionTreeNode)currSelected.SymbolicExpressionTreeNode.Clone(); 188 } 130 var node = (ISymbolicExpressionTreeNode)currSelected.SymbolicExpressionTreeNode.Clone(); 189 131 var originalNode = currSelected.SymbolicExpressionTreeNode; 132 190 133 ISymbolicExpressionTreeNode newNode = null; 191 134 var result = DialogResult.Cancel; … … 204 147 } 205 148 if (result != DialogResult.OK) return; 206 if (originalNode != newNode) { 207 var parent = originalNode.Parent; 208 int i = parent.IndexOfSubtree(originalNode); 209 parent.RemoveSubtree(i); 210 parent.InsertSubtree(i, newNode); 211 originalNodes[newNode] = originalNode; 212 currSelected.SymbolicExpressionTreeNode = newNode; 213 } 214 OnSymbolicExpressionTreeChanged(sender, EventArgs.Empty); 149 ModifyTree(Tree, originalNode.Parent, originalNode, newNode); // this will replace the original node with the new node 150 currSelected = null; 215 151 } 216 152 217 153 private void cutToolStripMenuItem_Click(object sender, EventArgs e) { 218 154 lastOp = EditOp.CutSubtree; 155 if (tempNode != null) { 156 foreach (var subtree in tempNode.IterateNodesBreadth()) { 157 var vNode = GetVisualSymbolicExpressionTreeNode(subtree); 158 base.OnSymbolicExpressionTreeNodeClicked(vNode, null); 159 if (subtree.Parent != null) { 160 var vArc = GetVisualSymbolicExpressionTreeNodeConnection(subtree.Parent, subtree); 161 vArc.LineColor = Color.Black; 162 } 163 } 164 } 219 165 tempNode = currSelected.SymbolicExpressionTreeNode; 220 166 foreach (var node in tempNode.IterateNodesPostfix()) { … … 229 175 } 230 176 } 177 currSelected = null; 231 178 Repaint(); 232 179 } 233 234 180 private void copyToolStripMenuItem_Click(object sender, EventArgs e) { 235 181 lastOp = EditOp.CopySubtree; 182 if (tempNode != null) { 183 foreach (var subtree in tempNode.IterateNodesBreadth()) { 184 var vNode = GetVisualSymbolicExpressionTreeNode(subtree); 185 base.OnSymbolicExpressionTreeNodeClicked(vNode, null); 186 if (subtree.Parent != null) { 187 var vArc = GetVisualSymbolicExpressionTreeNodeConnection(subtree.Parent, subtree); 188 vArc.LineColor = Color.Black; 189 } 190 } 191 } 236 192 tempNode = currSelected.SymbolicExpressionTreeNode; 237 193 foreach (var node in tempNode.IterateNodesPostfix()) { … … 245 201 } 246 202 } 203 currSelected = null; 247 204 Repaint(); 248 205 } 249 250 206 private void removeNodeToolStripMenuItem_Click(object sender, EventArgs e) { 251 207 lastOp = EditOp.RemoveNode; 252 208 var node = currSelected.SymbolicExpressionTreeNode; 253 var parent = node.Parent; 254 if (parent == null || parent.Symbol is StartSymbol || parent.Symbol is ProgramRootSymbol) 255 return; // the operation would result in the deletion of the entire tree 256 if (parent.Symbol.MaximumArity >= node.SubtreeCount + parent.SubtreeCount - 1) { // -1 because tempNode will be removed 257 parent.RemoveSubtree(parent.IndexOfSubtree(node)); 258 for (int i = node.SubtreeCount - 1; i >= 0; --i) { 259 var child = node.GetSubtree(i); 260 node.RemoveSubtree(i); 261 parent.AddSubtree(child); 262 } 263 } 264 OnSymbolicExpressionTreeChanged(sender, e); 209 ModifyTree(Tree, node.Parent, node, null, removeSubtree: false); 265 210 currSelected = null; // because the currently selected node was just deleted 266 211 } 267 268 212 private void removeSubtreeToolStripMenuItem_Click(object sender, EventArgs e) { 269 lastOp = EditOp.Remove Subtree;213 lastOp = EditOp.RemoveNode; 270 214 var node = currSelected.SymbolicExpressionTreeNode; 271 var parent = node.Parent; 272 if (parent == null || parent.Symbol is StartSymbol || parent.Symbol is ProgramRootSymbol) 273 return; // the operation makes no sense as it would result in the deletion of the entire tree 274 parent.RemoveSubtree(parent.IndexOfSubtree(node)); 275 OnSymbolicExpressionTreeChanged(sender, e); 215 ModifyTree(Tree, node.Parent, node, null, removeSubtree: true); 276 216 currSelected = null; // because the currently selected node was just deleted 277 }278 217 contextMenuStrip.Close(); // avoid display of submenus since the action has already been performed 218 } 279 219 private void pasteToolStripMenuItem_Clicked(object sender, EventArgs e) { 280 if (!(lastOp == EditOp.CopyNode || lastOp == EditOp.CopySubtree || lastOp == EditOp.CutNode || lastOp == EditOp.CutSubtree)) 281 return; 220 if (!(lastOp == EditOp.CopySubtree || lastOp == EditOp.CutSubtree)) return; 282 221 // check if the copied/cut node (stored in the tempNode) can be inserted as a child of the current selected node 283 222 var node = currSelected.SymbolicExpressionTreeNode; … … 285 224 // check if the currently selected node can accept the copied node as a child 286 225 // no need to check the grammar, an arity check will do just fine here 287 if (node.Symbol.MaximumArity > node.SubtreeCount) { 288 switch (lastOp) { 289 case (EditOp.CutNode): { 290 // when cutting a node from the tree, it's children become children of it's parent 291 var parent = tempNode.Parent; 292 // arity checks to see if parent can accept node's children (we assume the grammar is already ok with that) 293 // (otherise, the 'cut' part of the operation will just not do anything) 294 if (parent.Symbol.MaximumArity >= tempNode.SubtreeCount + parent.SubtreeCount - 1) { // -1 because tempNode will be removed 295 parent.RemoveSubtree(parent.IndexOfSubtree(tempNode)); 296 for (int i = tempNode.SubtreeCount - 1; i >= 0; --i) { 297 var child = tempNode.GetSubtree(i); 298 tempNode.RemoveSubtree(i); 299 parent.AddSubtree(child); 300 } 301 lastOp = EditOp.CopyNode; 302 } 303 break; 304 } 305 case (EditOp.CutSubtree): { 306 // cut subtree 307 var parent = tempNode.Parent; 308 parent.RemoveSubtree(parent.IndexOfSubtree(tempNode)); 309 lastOp = EditOp.CopySubtree; // do this so the next paste will actually perform a copy 310 break; 311 } 312 case (EditOp.CopyNode): { 313 // copy node 314 var clone = (SymbolicExpressionTreeNode)tempNode.Clone(); 315 clone.Parent = tempNode.Parent; 316 tempNode = clone; 317 for (int i = tempNode.SubtreeCount - 1; i >= 0; --i) tempNode.RemoveSubtree(i); 318 break; 319 } 320 case (EditOp.CopySubtree): { 321 // copy subtree 322 var clone = (SymbolicExpressionTreeNode)tempNode.Clone(); 323 clone.Parent = tempNode.Parent; 324 tempNode = clone; 325 break; 326 } 327 } 328 node.AddSubtree(tempNode); 329 Tree = Tree; // hack in order to trigger the reinitialization of the dictionaries after new nodes appeared in the tree 330 OnSymbolicExpressionTreeChanged(sender, e); 331 currSelected = null; // because the tree changed and was completely redrawn 332 } 333 } 334 335 private bool IsValid(ISymbolicExpressionTree tree) { 336 if (tree.IterateNodesPostfix().Any(node => node.SubtreeCount < node.Symbol.MinimumArity || node.SubtreeCount > node.Symbol.MaximumArity)) { 337 treeState = TreeState.Invalid; 338 return false; 339 } 340 treeState = TreeState.Valid; 341 return true; 342 } 343 344 private void InteractiveSymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) { 345 var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 346 if (currSelected != null) { 347 currSelected.LineColor = originalNodes.ContainsKey(currSelected.SymbolicExpressionTreeNode) ? Color.DodgerBlue : Color.Black; 348 RepaintNode(currSelected); 349 } 350 currSelected = visualTreeNode; 351 if (currSelected != null) { 352 currSelected.LineColor = Color.LightGreen; 353 RepaintNode(currSelected); 354 } 226 if (node.Symbol.MaximumArity <= node.SubtreeCount) return; 227 switch (lastOp) { 228 case EditOp.CutSubtree: { 229 ModifyTree(Tree, tempNode.Parent, tempNode, null); //remove node from its original parent 230 ModifyTree(Tree, node, null, tempNode);//insert it as a child to the new parent 231 lastOp = EditOp.CopySubtree; //do this so the next paste will actually perform a copy 232 break; 233 } 234 case EditOp.CopySubtree: { 235 var clone = (SymbolicExpressionTreeNode)tempNode.Clone(); 236 clone.Parent = tempNode.Parent; 237 tempNode = clone; 238 ModifyTree(Tree, node, null, tempNode); 239 break; 240 } 241 } 242 currSelected = null; // because the tree will have changed 355 243 } 356 244 }
Note: See TracChangeset
for help on using the changeset viewer.