Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionGrammarEditorView.cs @ 7043

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

#1479: Hid the ProgramRootSymbol and the DefunSymbol in SymbolicExpressionGrammarEditorView.

File size: 16.2 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.Common;
28using HeuristicLab.Core.Views;
29using HeuristicLab.MainForm;
30using HeuristicLab.PluginInfrastructure;
31
32namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
33  [View("Symbolic Expression Grammar Editor")]
34  [Content(typeof(ISymbolicExpressionGrammar), true)]
35  public partial class SymbolicExpressionGrammarEditorView : NamedItemView {
36    public SymbolicExpressionGrammarEditorView() {
37      InitializeComponent();
38    }
39
40    public override bool ReadOnly {
41      get {
42        if ((Content != null) && Content.ReadOnly) return true;
43        return base.ReadOnly;
44      }
45      set {
46        if ((Content != null) && Content.ReadOnly) base.ReadOnly = true;
47        else base.ReadOnly = value;
48      }
49    }
50
51    public new ISymbolicExpressionGrammar Content {
52      get { return (ISymbolicExpressionGrammar)base.Content; }
53      set { base.Content = value; }
54    }
55
56    protected override void SetEnabledStateOfControls() {
57      base.SetEnabledStateOfControls();
58      addButton.Enabled = Content != null && !Content.ReadOnly;
59      removeButton.Enabled = Content != null && !Content.ReadOnly && symbolsTreeView.SelectedNode != null && !(symbolsTreeView.SelectedNode.Tag is IReadOnlySymbol);
60      copyButton.Enabled = Content != null && !Content.ReadOnly && symbolsTreeView.SelectedNode != null && !(symbolsTreeView.SelectedNode.Tag is IReadOnlySymbol);
61    }
62
63    protected override void OnContentChanged() {
64      base.OnContentChanged();
65      if (Content != null) {
66        symbolsTreeView.Nodes.Clear();
67        UpdateSymbolsTreeView();
68
69        symbolsTreeView.CollapseAll();
70        foreach (var node in IterateTreeNodes())
71          if (node.Checked) node.Expand();
72
73        allowedChildSymbolsControl.Grammar = Content;
74        allowedChildSymbolsControl.Symbol = null;
75        symbolDetailsViewHost.Content = null;
76      } else {
77        symbolsTreeView.Nodes.Clear();
78        allowedChildSymbolsControl.Grammar = null;
79        symbolDetailsViewHost.Content = null;
80      }
81    }
82
83    #region events
84    protected override void RegisterContentEvents() {
85      base.RegisterContentEvents();
86      Content.ReadOnlyChanged += new System.EventHandler(Content_ReadOnlyChanged);
87      Content.Changed += new System.EventHandler(Content_Changed);
88    }
89    protected override void DeregisterContentEvents() {
90      Content.ReadOnlyChanged -= new System.EventHandler(Content_ReadOnlyChanged);
91      Content.Changed -= new System.EventHandler(Content_Changed);
92      base.DeregisterContentEvents();
93    }
94
95    private void Content_ReadOnlyChanged(object sender, EventArgs e) {
96      ReadOnly = Content.ReadOnly;
97    }
98
99    private void Content_Changed(object sender, EventArgs e) {
100      ISymbol symbol = null;
101      if (symbolsTreeView.SelectedNode != null)
102        symbol = (ISymbol)symbolsTreeView.SelectedNode.Tag;
103
104      allowedChildSymbolsControl.Grammar = Content;
105
106      UpdateSymbolsTreeView();
107      if (symbol != null && Content.ContainsSymbol(symbol)) {
108        symbolsTreeView.SelectedNode = IterateTreeNodes().Where(n => n.Tag == symbol).ToList().FirstOrDefault();
109        UpdateSymbolDetailsViews();
110      }
111    }
112    #endregion
113
114    private void UpdateSymbolsTreeView() {
115      var symbols = Content.Symbols.ToList();
116      foreach (var treeNode in IterateTreeNodes().ToList()) {
117        var symbol = treeNode.Tag as ISymbol;
118        if (!symbols.Contains(symbol))
119          treeNode.Remove();
120      }
121
122      var groupSymbols = symbols.OfType<GroupSymbol>().ToList();
123      var topLevelSymbols = Content.Symbols.Where(s => !groupSymbols.Any(g => g.Symbols.Contains(s)));
124      UpdateChildTreeNodes(symbolsTreeView.Nodes, topLevelSymbols);
125
126      RebuildImageList();
127    }
128
129    private void UpdateChildTreeNodes(TreeNodeCollection collection, IEnumerable<ISymbol> symbols) {
130      foreach (ISymbol symbol in symbols) {
131        if (symbol is ProgramRootSymbol) continue;
132        if (symbol is Defun) continue;
133
134        TreeNode node = collection.Cast<TreeNode>().Where(n => n.Tag == symbol).FirstOrDefault();
135        if (node == null) {
136          node = new TreeNode();
137          node.Tag = symbol;
138          collection.Add(node);
139        }
140        node.Checked = symbol.Enabled;
141        node.Text = symbol.Name;
142
143        var groupSymbol = symbol as GroupSymbol;
144        if (groupSymbol != null) UpdateChildTreeNodes(node.Nodes, groupSymbol.Symbols);
145      }
146    }
147
148    private void symbolsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
149      if (e.Action != TreeViewAction.Unknown) UpdateSymbolDetailsViews();
150
151      removeButton.Enabled = symbolsTreeView.SelectedNode != null && !(symbolsTreeView.SelectedNode.Tag is IReadOnlySymbol);
152      copyButton.Enabled = symbolsTreeView.SelectedNode != null && !(symbolsTreeView.SelectedNode.Tag is IReadOnlySymbol);
153    }
154
155    private void symbolsTreeView_AfterCheck(object sender, TreeViewEventArgs e) {
156      if (e.Action != TreeViewAction.Unknown) {
157        Content.StartGrammarManipulation();
158        allowedChildSymbolsControl.Symbol = null;
159        var symbol = (ISymbol)e.Node.Tag;
160        symbol.Enabled = e.Node.Checked;
161        foreach (var node in IterateTreeNodes())
162          node.Checked = ((ISymbol)node.Tag).Enabled;
163
164        Content.FinishedGrammarManipulation();
165      }
166    }
167
168    #region drag & drop operations
169    private GroupSymbol parentOfDraggedSymbol;
170    private void symbolsTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
171      if (!Locked) {
172        var treeNode = e.Item as TreeNode;
173        if (treeNode.Parent != null) parentOfDraggedSymbol = treeNode.Parent.Tag as GroupSymbol;
174        var data = new DataObject();
175        data.SetData(HeuristicLab.Common.Constants.DragDropDataFormat, treeNode.Tag);
176        validDragOperation = true;
177        DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Move);
178      }
179    }
180
181
182    private bool validDragOperation;
183    private void symbolsTreeView_DragEnter(object sender, DragEventArgs e) {
184      validDragOperation = false;
185      if (Content == null) return;
186
187      var data = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
188      var symbol = data as ISymbol;
189      if (symbol != null && !(symbol is IReadOnlySymbol)) validDragOperation = true;
190    }
191    private void symbolsTreeView_DragOver(object sender, DragEventArgs e) {
192      e.Effect = DragDropEffects.None;
193      if (validDragOperation) {
194        GroupSymbol groupSymbol = null;
195        Point mouse = symbolsTreeView.PointToClient(new Point(e.X, e.Y));
196        TreeNode node = symbolsTreeView.GetNodeAt(mouse);
197        if (node == null) return;
198        groupSymbol = node.Tag as GroupSymbol;
199        if (groupSymbol == null) return;
200        var symbol = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat);
201        if (symbol == groupSymbol) return;
202
203        if (e.AllowedEffect.HasFlag(DragDropEffects.Copy)) e.Effect = DragDropEffects.Copy;
204      }
205    }
206    private void symbolsTreeView_DragDrop(object sender, DragEventArgs e) {
207      var symbol = e.Data.GetData(HeuristicLab.Common.Constants.DragDropDataFormat) as ISymbol;
208
209      GroupSymbol groupSymbol = null;
210      Point mouse = symbolsTreeView.PointToClient(new Point(e.X, e.Y));
211      TreeNode node = symbolsTreeView.GetNodeAt(mouse);
212      if (node != null) groupSymbol = node.Tag as GroupSymbol;
213      if (node != null && groupSymbol == null) groupSymbol = node.Parent.Tag as GroupSymbol;
214
215      Content.StartGrammarManipulation();
216      Cloner cloner = new Cloner();
217      var clonedSymbol = cloner.Clone(symbol);
218      ChangeDuplicateSymbolNames(clonedSymbol);
219
220      if (groupSymbol != null) groupSymbol.SymbolsCollection.Add(clonedSymbol);
221      else Content.AddSymbol(clonedSymbol);
222
223      UpdateGrammerConstraintsForClonedSymbol(symbol, cloner);
224      Content.FinishedGrammarManipulation();
225    }
226    #endregion
227
228    private void symbolsTreeView_MouseDown(object sender, MouseEventArgs e) {
229      // enables deselection of treeNodes
230      Point coordinates = new Point(e.X, e.Y);
231      TreeNode node = symbolsTreeView.GetNodeAt(coordinates);
232      if (e.Button == System.Windows.Forms.MouseButtons.Left && node == null) {
233        symbolsTreeView.SelectedNode = null;
234        symbolDetailsViewHost.Content = null;
235        SetEnabledStateOfControls();
236      }
237    }
238
239    private void symbolsTreeView_KeyDown(object sender, KeyEventArgs e) {
240      if (ReadOnly) return;
241      if (symbolsTreeView.SelectedNode == null) return;
242      if (e.KeyCode != Keys.Delete) return;
243
244      var symbol = (ISymbol)symbolsTreeView.SelectedNode.Tag;
245      if (!(symbol is IReadOnlySymbol))
246        Content.RemoveSymbol(symbol);
247
248      SetEnabledStateOfControls();
249      UpdateSymbolDetailsViews();
250      RebuildImageList();
251    }
252
253    #region button events
254    private TypeSelectorDialog typeSelectorDialog;
255    private void addButton_Click(object sender, EventArgs e) {
256      if (typeSelectorDialog == null) {
257        typeSelectorDialog = new TypeSelectorDialog();
258        typeSelectorDialog.Caption = "Select Symbol";
259        typeSelectorDialog.TypeSelector.Caption = "Available Symbols";
260        typeSelectorDialog.TypeSelector.Configure(typeof(ISymbol), false, false, (t) => { return !typeof(IReadOnlySymbol).IsAssignableFrom(t); });
261      }
262      if (typeSelectorDialog.ShowDialog(this) == DialogResult.OK) {
263        try {
264          ISymbol symbol = (ISymbol)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType();
265          ChangeDuplicateSymbolNames(symbol);
266          GroupSymbol groupSymbol = null;
267
268          TreeNode selectedNode = symbolsTreeView.SelectedNode;
269          if (selectedNode != null) {
270            groupSymbol = selectedNode.Tag as GroupSymbol;
271            if (groupSymbol == null && selectedNode.Parent != null) groupSymbol = selectedNode.Parent.Tag as GroupSymbol;
272          }
273          if (groupSymbol != null) groupSymbol.SymbolsCollection.Add(symbol);
274          else Content.AddSymbol(symbol);
275        }
276        catch (Exception ex) {
277          ErrorHandling.ShowErrorDialog(this, ex);
278        }
279      }
280    }
281
282    private void copyButton_Click(object sender, EventArgs e) {
283      var symbol = symbolsTreeView.SelectedNode.Tag as ISymbol;
284      if (symbol != null && !(symbol is IReadOnlySymbol)) {
285
286        Content.StartGrammarManipulation();
287        Cloner cloner = new Cloner();
288        var clonedSymbol = cloner.Clone(symbol);
289        ChangeDuplicateSymbolNames(clonedSymbol);
290
291        GroupSymbol groupSymbol = null;
292        if (symbolsTreeView.SelectedNode.Parent != null) groupSymbol = symbolsTreeView.SelectedNode.Parent.Tag as GroupSymbol;
293
294        if (groupSymbol != null) groupSymbol.SymbolsCollection.Add(clonedSymbol);
295        else Content.AddSymbol(clonedSymbol);
296
297        UpdateGrammerConstraintsForClonedSymbol(symbol, cloner);
298        Content.FinishedGrammarManipulation();
299      }
300    }
301
302    private void removeButton_Click(object sender, EventArgs e) {
303      var symbol = symbolsTreeView.SelectedNode.Tag as ISymbol;
304      if (symbol != null && !(symbol is IReadOnlySymbol)) {
305        Content.RemoveSymbol(symbol);
306      }
307    }
308
309    private void showDetailsCheckBox_CheckedChanged(object sender, EventArgs e) {
310      splitContainer1.Panel2Collapsed = !showDetailsCheckBox.Checked;
311    }
312
313    private void showSampleTreeButton_Click(object sender, EventArgs e) {
314      SymbolicExpressionGrammarSampleExpressionTreeView view = new SymbolicExpressionGrammarSampleExpressionTreeView();
315      view.Content = Content;
316      view.Show();
317    }
318
319    #endregion
320
321    #region helpers
322    private void UpdateGrammerConstraintsForClonedSymbol(ISymbol symbol, Cloner cloner) {
323      foreach (var s in symbol.Flatten().Where(x => !(x is GroupSymbol))) {
324        if (!cloner.ClonedObjectRegistered(s)) throw new InvalidOperationException();
325        var clone = cloner.Clone(s);
326        Content.SetSubtreeCount(clone, Content.GetMinimumSubtreeCount(s), Content.GetMaximumSubtreeCount(s));
327        foreach (var childSymbol in Content.GetAllowedChildSymbols(s)) {
328          var newChildSymbol = childSymbol;
329          if (cloner.ClonedObjectRegistered(childSymbol)) newChildSymbol = cloner.Clone(childSymbol);
330          Content.AddAllowedChildSymbol(clone, newChildSymbol);
331        }
332        for (int i = 0; i < Content.GetMaximumSubtreeCount(s); i++) {
333          foreach (var childSymbol in Content.GetAllowedChildSymbols(s, i)) {
334            var newChildSymbol = childSymbol;
335            if (cloner.ClonedObjectRegistered(childSymbol)) newChildSymbol = cloner.Clone(childSymbol);
336            Content.AddAllowedChildSymbol(clone, newChildSymbol, i);
337          }
338        }
339      }
340    }
341
342    private void ChangeDuplicateSymbolNames(ISymbol symbol) {
343      foreach (var s in symbol.Flatten()) {
344        var originalSymbolName = s.Name;
345        int i = 1;
346        while (Content.ContainsSymbol(s)) {
347          s.Name = originalSymbolName + i;
348          i++;
349        }
350      }
351    }
352
353    private void UpdateSymbolDetailsViews() {
354      if (symbolsTreeView.SelectedNode != null) {
355        symbolDetailsViewHost.Content = (ISymbol)symbolsTreeView.SelectedNode.Tag;
356        allowedChildSymbolsControl.Symbol = (ISymbol)symbolsTreeView.SelectedNode.Tag;
357      } else {
358        symbolDetailsViewHost.Content = null;
359        allowedChildSymbolsControl.Symbol = null;
360      }
361    }
362
363    private IEnumerable<TreeNode> IterateTreeNodes(TreeNode node = null) {
364      TreeNodeCollection nodes;
365      if (node == null)
366        nodes = symbolsTreeView.Nodes;
367      else {
368        nodes = node.Nodes;
369        yield return node;
370      }
371
372      foreach (var childNode in nodes.OfType<TreeNode>())
373        foreach (var n in IterateTreeNodes(childNode))
374          yield return n;
375    }
376
377    protected virtual void RebuildImageList() {
378      symbolsTreeView.ImageList.Images.Clear();
379      foreach (TreeNode treeNode in IterateTreeNodes()) {
380        var symbol = (ISymbol)treeNode.Tag;
381        symbolsTreeView.ImageList.Images.Add(symbol == null ? HeuristicLab.Common.Resources.VSImageLibrary.Nothing : symbol.ItemImage);
382        treeNode.ImageIndex = symbolsTreeView.ImageList.Images.Count - 1;
383      }
384    }
385
386    //necessary code to handle dock correctly regarding the expanded nodes
387    bool[] expandendedState;
388    protected override void OnHandleCreated(EventArgs e) {
389      base.OnHandleCreated(e);
390      if (expandendedState == null) return;
391      var nodes = IterateTreeNodes().ToList();
392      for (int i = 0; i < nodes.Count; i++)
393        if (expandendedState[i]) nodes[i].Expand();
394    }
395    protected override void OnHandleDestroyed(EventArgs e) {
396      base.OnHandleDestroyed(e);
397      var nodes = IterateTreeNodes().ToList();
398      expandendedState = new bool[nodes.Count];
399      for (int i = 0; i < nodes.Count; i++)
400        expandendedState[i] = nodes[i].IsExpanded;
401    }
402    #endregion
403  }
404
405  //this class is necessary to prevent double clicks which do not fire the checkbox checked event
406  internal class CheckBoxTreeView : TreeView {
407    protected override void WndProc(ref Message m) {
408      // Suppress WM_LBUTTONDBLCLK
409      if (m.Msg == 0x203) { m.Result = IntPtr.Zero; } else base.WndProc(ref m);
410    }
411  }
412}
Note: See TracBrowser for help on using the repository browser.