Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.TimeSeries/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionGrammarEditorView.cs @ 7461

Last change on this file since 7461 was 7268, checked in by gkronber, 13 years ago

#1081: merged r7214:7266 from trunk into time series branch.

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