Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1479: Corrected bug concerning the deletion of symbols in the grammar editor.

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