Free cookie consent management tool by TermsFeed Policy Generator

source: branches/GP.Grammar.Editor/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionGrammarEditorView.cs @ 6387

Last change on this file since 6387 was 6387, checked in by mkommend, 13 years ago

#1540: Added min and max arity to symbols and renamed SymbolicExpressionTreeNode.SubtreesCount to SymbolicExpressionTreeNode.SubtreeCount.

File size: 14.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.Windows.Forms;
27using HeuristicLab.Collections;
28using HeuristicLab.Common;
29using HeuristicLab.Core.Views;
30using HeuristicLab.MainForm;
31using HeuristicLab.PluginInfrastructure;
32
33namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
34  [View("Symbolic Expression Grammar Editor")]
35  [Content(typeof(ISymbolicExpressionGrammar), false)]
36  public partial class SymbolicExpressionGrammarEditorView : NamedItemView {
37    private ObservableList<ISymbolicExpressionTreeNode> selectedSymbolicExpressionTreeNodes;
38
39    public SymbolicExpressionGrammarEditorView() {
40      InitializeComponent();
41      selectedSymbolicExpressionTreeNodes = new ObservableList<ISymbolicExpressionTreeNode>();
42    }
43
44    public override bool ReadOnly {
45      get {
46        if ((Content != null) && Content.ReadOnly) return true;
47        return base.ReadOnly;
48      }
49      set {
50        if ((Content != null) && Content.ReadOnly) base.ReadOnly = true;
51        else base.ReadOnly = value;
52      }
53    }
54
55    public new ISymbolicExpressionGrammar Content {
56      get { return (ISymbolicExpressionGrammar)base.Content; }
57      set { base.Content = value; }
58    }
59
60    #region events
61    protected override void RegisterContentEvents() {
62      base.RegisterContentEvents();
63      Content.ReadOnlyChanged += new System.EventHandler(Content_ReadOnlyChanged);
64      Content.Changed += new System.EventHandler(Content_Changed);
65    }
66    protected override void DeregisterContentEvents() {
67      Content.ReadOnlyChanged -= new System.EventHandler(Content_ReadOnlyChanged);
68      Content.Changed -= new System.EventHandler(Content_Changed);
69      base.DeregisterContentEvents();
70    }
71
72    private void Content_ReadOnlyChanged(object sender, EventArgs e) {
73      ReadOnly = Content.ReadOnly;
74    }
75
76    private void Content_Changed(object sender, EventArgs e) {
77      ISymbol symbol = null;
78      if (symbolsTreeView.SelectedNode != null)
79        symbol = (ISymbol)symbolsTreeView.SelectedNode.Tag;
80
81      RebuildSymbolsTreeView();
82      if (symbol != null && Content.ContainsSymbol(symbol)) {
83        BuildAllowedChildSymbolsTree(symbol);
84        symbolDetailsViewHost.Content = symbol;
85        symbolsTreeView.SelectedNode = IterateSymbolTreeNodes().Where(n => n.Tag == symbol).ToList().FirstOrDefault();
86      }
87    }
88    #endregion
89
90    protected override void SetEnabledStateOfControls() {
91      base.SetEnabledStateOfControls();
92    }
93
94    protected override void OnContentChanged() {
95      base.OnContentChanged();
96      if (Content != null) {
97        RebuildSymbolsTreeView();
98        allowedChildSymbolsControl.Tree = null;
99        symbolDetailsViewHost.Content = null;
100      } else {
101        symbolsTreeView.Nodes.Clear();
102        allowedChildSymbolsControl.Tree = null;
103        symbolDetailsViewHost.Content = null;
104      }
105    }
106
107    private void AddChildTreeNodes(TreeNodeCollection collection, IEnumerable<ISymbol> symbols) {
108      foreach (ISymbol symbol in symbols) {
109        var node = new TreeNode();
110        node.Name = symbol.Name;
111        node.Text = symbol.Name;
112        node.Tag = symbol;
113        node.Checked = symbol.Enabled;
114        collection.Add(node);
115        var groupSymbol = symbol as GroupSymbol;
116        if (groupSymbol != null) AddChildTreeNodes(node.Nodes, groupSymbol.Symbols);
117      }
118    }
119
120    private void symbolsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
121      if (e.Action != TreeViewAction.Unknown) {
122        var symbol = (ISymbol)e.Node.Tag;
123        symbolDetailsViewHost.Content = symbol;
124        selectedSymbolicExpressionTreeNodes.Clear();
125        BuildAllowedChildSymbolsTree(symbol);
126      }
127      removeButton.Enabled = symbolsTreeView.SelectedNode != null && !(symbolsTreeView.SelectedNode.Tag is IReadOnlySymbol);
128    }
129
130    private void symbolsTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
131      if (e.Action != TreeViewAction.Unknown) {
132        DeregisterContentEvents();
133        var symbol = (ISymbol)e.Node.Tag;
134        symbol.Enabled = e.Node.Checked;
135        foreach (var node in IterateSymbolTreeNodes())
136          node.Checked = ((ISymbol)node.Tag).Enabled;
137
138        if (symbolsTreeView.SelectedNode != null) {
139          symbol = (ISymbol)symbolsTreeView.SelectedNode.Tag;
140          selectedSymbolicExpressionTreeNodes.Clear();
141          BuildAllowedChildSymbolsTree(symbol);
142        }
143        RegisterContentEvents();
144      }
145    }
146
147    private void RebuildSymbolsTreeView() {
148      symbolsTreeView.Nodes.Clear();
149      var symbols = Content.Symbols.ToList();
150      var groupSymbols = symbols.OfType<GroupSymbol>().ToList();
151      var topLevelSymbols = Content.Symbols.Where(s => !groupSymbols.Any(g => g.Symbols.Contains(s)));
152      AddChildTreeNodes(symbolsTreeView.Nodes, topLevelSymbols);
153
154      RebuildImageList();
155      symbolsTreeView.ExpandAll();
156    }
157
158    private void BuildAllowedChildSymbolsTree(ISymbol symbol) {
159      var tree = new SymbolicExpressionTree(new SymbolicExpressionTreeNode(symbol));
160
161      if (Content.GetMaximumSubtreeCount(symbol) > 0) {
162        for (int i = 0; i < Content.GetMaximumSubtreeCount(symbol); i++) {
163          var node = new DummySymbol("Subtree " + i).CreateTreeNode();
164          foreach (var childSymbol in Content.GetAllowedChildSymbols(symbol, i)) {
165            node.AddSubtree(new SymbolicExpressionTreeNode(childSymbol));
166          }
167          tree.Root.AddSubtree(node);
168        }
169      }
170      allowedChildSymbolsControl.Tree = tree;
171      UpdateSelectedSymbolicExpressionTreeNodes();
172    }
173
174    private void symbolicExpressionTreeChart_SymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
175      if ((Control.ModifierKeys & Keys.Control) == 0)
176        selectedSymbolicExpressionTreeNodes.Clear();
177
178      VisualSymbolicExpressionTreeNode clickedNode = (VisualSymbolicExpressionTreeNode)sender;
179      var selectedNode = clickedNode.SymbolicExpressionTreeNode;
180      if (selectedNode.SubtreeCount == 0) {
181        if (!selectedSymbolicExpressionTreeNodes.Contains(selectedNode))
182          selectedSymbolicExpressionTreeNodes.Add(selectedNode);
183        else
184          selectedSymbolicExpressionTreeNodes.Remove(selectedNode);
185      }
186
187      UpdateSelectedSymbolicExpressionTreeNodes();
188    }
189
190    private void symbolicExpressionTreeChart_KeyDown(object sender, KeyEventArgs e) {
191      if (e.KeyCode == Keys.Delete) {
192        DeregisterContentEvents();
193        var root = allowedChildSymbolsControl.Tree.Root;
194        foreach (var node in selectedSymbolicExpressionTreeNodes) {
195          int argIndex = root.IndexOfSubtree(node.Parent);
196          Content.RemoveAllowedChildSymbol(root.Symbol, node.Symbol, argIndex);
197        }
198        RegisterContentEvents();
199        selectedSymbolicExpressionTreeNodes.Clear();
200        BuildAllowedChildSymbolsTree(root.Symbol);
201      }
202    }
203
204    private void symbolsTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
205      if (!Locked) {
206        DataObject data = new DataObject();
207        data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, ((TreeNode)e.Item).Tag);
208        DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
209      }
210    }
211
212    private bool validDragOperation;
213    private void symbolicExpressionTreeChart_DragEnter(object sender, DragEventArgs e) {
214      validDragOperation = false;
215      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
216      var symbol = data as ISymbol;
217      var symbols = data as IEnumerable<ISymbol>;
218      if (symbol != null && !(symbol is IReadOnlySymbol) && !Content.ContainsSymbol(symbol)) validDragOperation = true;
219      else if (symbols != null && symbols.All(s => !(symbol is IReadOnlySymbol) && Content.ContainsSymbol(s))) validDragOperation = true;
220    }
221
222    private void symbolicExpressionTreeChart_DragOver(object sender, DragEventArgs e) {
223      e.Effect = DragDropEffects.None;
224      if (validDragOperation) {
225        Point coordinates = allowedChildSymbolsControl.PointToClient(new Point(e.X, e.Y));
226        var visualNode = allowedChildSymbolsControl.FindVisualSymbolicExpressionTreeNodeAt(coordinates.X, coordinates.Y);
227        if (visualNode != null) {
228          var node = visualNode.SymbolicExpressionTreeNode;
229          var root = allowedChildSymbolsControl.Tree.Root;
230          if (root.Symbol is ProgramRootSymbol) return;
231          if (node == root || node.Parent == root) e.Effect = DragDropEffects.Copy;
232        }
233      }
234    }
235
236    private void symbolicExpressionTreeChart_DragDrop(object sender, DragEventArgs e) {
237      Point coordinates = allowedChildSymbolsControl.PointToClient(new Point(e.X, e.Y));
238      var node = allowedChildSymbolsControl.FindVisualSymbolicExpressionTreeNodeAt(coordinates.X, coordinates.Y);
239      var root = allowedChildSymbolsControl.Tree.Root;
240
241      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
242      var symbol = data as ISymbol;
243      var symbols = data as IEnumerable<ISymbol>;
244
245      DeregisterContentEvents();
246      if (node.SymbolicExpressionTreeNode == root) {
247        if (symbol != null)
248          Content.AddAllowedChildSymbol(root.Symbol, symbol);
249        else if (symbols != null)
250          foreach (var s in symbols) Content.AddAllowedChildSymbol(root.Symbol, s);
251      } else {
252        int argumentIndex = root.IndexOfSubtree(node.SymbolicExpressionTreeNode);
253        if (symbol != null)
254          Content.AddAllowedChildSymbol(root.Symbol, symbol, argumentIndex);
255        else if (symbols != null)
256          foreach (var s in symbols) Content.AddAllowedChildSymbol(root.Symbol, s, argumentIndex);
257      }
258      RegisterContentEvents();
259      BuildAllowedChildSymbolsTree(root.Symbol);
260    }
261
262    private void UpdateSelectedSymbolicExpressionTreeNodes() {
263      foreach (var node in allowedChildSymbolsControl.Tree.IterateNodesPrefix()) {
264        var visualNode = allowedChildSymbolsControl.GetVisualSymbolicExpressionTreeNode(node);
265        if (!selectedSymbolicExpressionTreeNodes.Contains(node)) {
266          visualNode.FillColor = Color.White;
267          visualNode.LineColor = Color.Black;
268        } else {
269          visualNode.FillColor = Color.WhiteSmoke;
270          visualNode.LineColor = Color.DarkOrange;
271        }
272      }
273      allowedChildSymbolsControl.Repaint();
274    }
275
276    private TypeSelectorDialog typeSelectorDialog;
277    private void addButton_Click(object sender, EventArgs e) {
278      if (typeSelectorDialog == null) {
279        typeSelectorDialog = new TypeSelectorDialog();
280        typeSelectorDialog.Caption = "Select Symbol";
281        typeSelectorDialog.TypeSelector.Caption = "Available Symbols";
282        typeSelectorDialog.TypeSelector.Configure(typeof(ISymbol), false, false, (t) => { return !typeof(IReadOnlySymbol).IsAssignableFrom(t); });
283      }
284      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
285        try {
286          ISymbol symbol = (ISymbol)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
287          var originalSymbolName = symbol.Name;
288          int i = 1;
289          while (Content.ContainsSymbol(symbol)) {
290            symbol.Name = originalSymbolName + i;
291            i++;
292          }
293
294          var selectedNode = symbolsTreeView.SelectedNode;
295          GroupSymbol groupSymbol = null;
296          while (selectedNode != null) {
297            groupSymbol = selectedNode.Tag as GroupSymbol;
298            if (groupSymbol != null && Content.ContainsSymbol(groupSymbol)) break;
299          }
300
301          if (groupSymbol != null && Content.ContainsSymbol(groupSymbol)) groupSymbol.SymbolsCollection.Add(symbol);
302          else Content.AddSymbol(symbol);
303        }
304        catch (Exception ex) {
305          ErrorHandling.ShowErrorDialog(this, ex);
306        }
307      }
308    }
309
310    private void removeButton_Click(object sender, EventArgs e) {
311      var symbol = symbolsTreeView.SelectedNode.Tag as ISymbol;
312      if (symbol != null && !(symbol is IReadOnlySymbol))
313        Content.RemoveSymbol(symbol);
314      removeButton.Enabled = false;
315      allowedChildSymbolsControl.Tree = null;
316      symbolDetailsViewHost.Content = null;
317    }
318
319    private void showDetailsCheckBox_CheckedChanged(object sender, EventArgs e) {
320      splitContainer1.Panel2Collapsed = !showDetailsCheckBox.Checked;
321    }
322
323    #region helpers
324    private IEnumerable<TreeNode> IterateSymbolTreeNodes(TreeNode node = null) {
325      TreeNodeCollection nodes;
326      if (node == null)
327        nodes = symbolsTreeView.Nodes;
328      else {
329        nodes = node.Nodes;
330        yield return node;
331      }
332
333      foreach (var childNode in nodes.OfType<TreeNode>())
334        foreach (var n in IterateSymbolTreeNodes(childNode))
335          yield return n;
336    }
337
338    protected virtual void RebuildImageList() {
339      symbolsTreeView.ImageList.Images.Clear();
340      foreach (TreeNode treeNode in IterateSymbolTreeNodes()) {
341        var symbol = (ISymbol)treeNode.Tag;
342        symbolsTreeView.ImageList.Images.Add(symbol == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : symbol.ItemImage);
343        treeNode.ImageIndex = symbolsTreeView.ImageList.Images.Count - 1;
344      }
345    }
346    #endregion
347  }
348
349  [NonDiscoverableType]
350  internal class DummySymbol : Symbol {
351    private const int minimumArity = 1;
352    private const int maximumArity = byte.MaxValue;
353
354    public override int MinimumArity {
355      get { return minimumArity; }
356    }
357    public override int MaximumArity {
358      get { return maximumArity; }
359    }
360
361    public DummySymbol(DummySymbol original, Cloner cloner) : base(original, cloner) { }
362    public DummySymbol(string name) : base(name, "DummySymbol for views") { }
363    public override IDeepCloneable Clone(Cloner cloner) { return new DummySymbol(this, cloner); }
364  }
365}
Note: See TracBrowser for help on using the repository browser.