Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core.Views/3.3/OperatorTreeView.cs @ 2664

Last change on this file since 2664 was 2664, checked in by swagner, 15 years ago

Abandoned policy that the names of all abstract base classes have to end in "Base" (#95)

File size: 17.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 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.ComponentModel;
25using System.Drawing;
26using System.Data;
27using System.Text;
28using System.Windows.Forms;
29using HeuristicLab.PluginInfrastructure;
30using HeuristicLab.Common;
31using HeuristicLab.MainForm;
32using HeuristicLab.Collections;
33
34namespace HeuristicLab.Core.Views {
35  /// <summary>
36  /// The visual representation of an <see cref="OperatorGraph"/>.
37  /// </summary>
38  [Content(typeof(IOperator), false)]
39  public partial class OperatorTreeView : ItemView {
40    private Dictionary<IOperatorParameter, List<TreeNode>> operatorParameterNodeTable;
41    private Dictionary<IOperator, List<TreeNode>> operatorNodeTable;
42    private Dictionary<IObservableKeyedCollection<string, IParameter>, IOperator> parametersOperatorTable;
43
44    /// <summary>
45    /// Gets or sets the operator graph to represent visually.
46    /// </summary>
47    /// <remarks>Uses property <see cref="ViewBase.Item"/> of base class <see cref="ViewBase"/>.
48    /// No own data storage present.</remarks>
49    public IOperator Operator {
50      get { return (IOperator)Item; }
51      set { base.Item = value; }
52    }
53
54    /// <summary>
55    /// Initializes a new instance of <see cref="OperatorGraphView"/> with caption "Operator Graph".
56    /// </summary>
57    public OperatorTreeView() {
58      InitializeComponent();
59      graphTreeView.Sorted = true;
60      operatorParameterNodeTable = new Dictionary<IOperatorParameter, List<TreeNode>>();
61      operatorNodeTable = new Dictionary<IOperator, List<TreeNode>>();
62      parametersOperatorTable = new Dictionary<IObservableKeyedCollection<string, IParameter>, IOperator>();
63      Caption = "Operator";
64    }
65    /// <summary>
66    /// Initializes a new instance of <see cref="OperatorGraphView"/>
67    /// with the given <paramref name="operatorGraph"/>.
68    /// </summary>
69    /// <remarks>Calls <see cref="OperatorGraphView()"/>.</remarks>
70    /// <param name="operatorGraph">The operator graph to represent visually.</param>
71    public OperatorTreeView(IOperator op)
72      : this() {
73      Operator = op;
74    }
75
76    /// <summary>
77    /// Updates all controls with the latest data of the model.
78    /// </summary>
79    /// <remarks>Calls <see cref="ViewBase.UpdateControls"/> of base class <see cref="ViewBase"/>.</remarks>
80    protected override void OnObjectChanged() {
81      base.OnObjectChanged();
82      if (graphTreeView.Nodes.Count > 0)
83        RemoveTreeNode(graphTreeView.Nodes[0]);
84      graphTreeView.Enabled = false;
85      Caption = "Operator";
86      if (Operator != null) {
87        Caption = Operator.Name + " (" + Operator.GetType().Name + ")";
88        TreeNode root = new TreeNode();
89        FillTreeNode(root, Operator);
90        graphTreeView.Nodes.Add(root);
91        graphTreeView.Enabled = true;
92      }
93    }
94
95    #region TreeNode Management
96    private TreeNode CreateTreeNode(IOperatorParameter operatorParameter) {
97      TreeNode node = new TreeNode();
98      node.Text = operatorParameter.Name + ": ";
99      SetOperatorParameterTag(node, operatorParameter);
100
101      if (!operatorParameterNodeTable.ContainsKey(operatorParameter)) {
102        operatorParameterNodeTable.Add(operatorParameter, new List<TreeNode>());
103        operatorParameter.ActualNameChanged += new EventHandler(operatorParameter_ActualNameChanged);
104        operatorParameter.ValueChanged += new EventHandler(operatorParameter_ValueChanged);
105      }
106      operatorParameterNodeTable[operatorParameter].Add(node);
107
108      IOperator op = operatorParameter.Value;
109      if (op == null)
110        node.Text += operatorParameter.ActualName;
111      else
112        FillTreeNode(node, op);
113
114      return node;
115    }
116    private void FillTreeNode(TreeNode node, IOperator op) {
117      if (!graphTreeView.ImageList.Images.ContainsKey(op.GetType().FullName))
118        graphTreeView.ImageList.Images.Add(op.GetType().FullName, op.ItemImage);
119
120      node.Text += op.Name;
121      node.ToolTipText = op.ItemName + ": " + op.ItemDescription;
122      node.ImageIndex = graphTreeView.ImageList.Images.IndexOfKey(op.GetType().FullName);
123      node.SelectedImageIndex = node.ImageIndex;
124      SetOperatorTag(node, op);
125
126      if (!operatorNodeTable.ContainsKey(op)) {
127        operatorNodeTable.Add(op, new List<TreeNode>());
128        op.NameChanged += new EventHandler(op_NameChanged);
129        op.BreakpointChanged += new EventHandler(op_BreakpointChanged);
130        parametersOperatorTable.Add(op.Parameters, op);
131        op.Parameters.ItemsAdded += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
132        op.Parameters.ItemsRemoved += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
133        op.Parameters.ItemsReplaced += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
134        op.Parameters.CollectionReset += new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
135      }
136      operatorNodeTable[op].Add(node);
137
138      if (op.Breakpoint)
139        node.ForeColor = Color.Red;
140
141      foreach (IParameter param in op.Parameters) {
142        if (param is IOperatorParameter)
143          node.Nodes.Add(new TreeNode());
144      }
145      node.Collapse();
146    }
147    private void ClearTreeNode(TreeNode node) {
148      while (node.Nodes.Count > 0)
149        RemoveTreeNode(node.Nodes[0]);
150
151      IOperator op = GetOperatorTag(node);
152      if (op != null) {
153        operatorNodeTable[op].Remove(node);
154        if (operatorNodeTable[op].Count == 0) {
155          op.NameChanged -= new EventHandler(op_NameChanged);
156          op.BreakpointChanged -= new EventHandler(op_BreakpointChanged);
157          operatorNodeTable.Remove(op);
158          op.Parameters.ItemsAdded -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
159          op.Parameters.ItemsRemoved -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
160          op.Parameters.ItemsReplaced -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
161          op.Parameters.CollectionReset -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
162          parametersOperatorTable.Remove(op.Parameters);
163        }
164      }
165      SetOperatorTag(node, null);
166    }
167    private void RemoveTreeNode(TreeNode node) {
168      ClearTreeNode(node);
169
170      IOperatorParameter opParam = GetOperatorParameterTag(node);
171      if (opParam != null) {
172        operatorParameterNodeTable[opParam].Remove(node);
173        if (operatorParameterNodeTable[opParam].Count == 0) {
174          opParam.ActualNameChanged -= new EventHandler(operatorParameter_ActualNameChanged);
175          opParam.ValueChanged -= new EventHandler(operatorParameter_ValueChanged);
176          operatorParameterNodeTable.Remove(opParam);
177        }
178      }
179      SetOperatorParameterTag(node, null);
180      node.Remove();
181    }
182    private void AddParameterNodes(IOperator op, IEnumerable<IParameter> parameters) {
183      foreach (IParameter param in parameters) {
184        IOperatorParameter opParam = param as IOperatorParameter;
185        if (opParam != null) {
186          foreach (TreeNode node in operatorNodeTable[op])
187            node.Nodes.Add(CreateTreeNode(opParam));
188        }
189      }
190    }
191    private void RemoveParameterNodes(IEnumerable<IParameter> parameters) {
192      foreach (IParameter param in parameters) {
193        IOperatorParameter opParam = param as IOperatorParameter;
194        if (opParam != null) {
195          while (operatorParameterNodeTable.ContainsKey(opParam))
196            RemoveTreeNode(operatorParameterNodeTable[opParam][0]);
197        }
198      }
199    }
200    #endregion
201
202    #region Parameter and Operator Events
203    private void operatorParameter_ActualNameChanged(object sender, EventArgs e) {
204      if (InvokeRequired)
205        Invoke(new EventHandler(operatorParameter_ActualNameChanged), sender, e);
206      else {
207        IOperatorParameter opParam = (IOperatorParameter)sender;
208        if (opParam.Value == null) {
209          foreach (TreeNode node in operatorParameterNodeTable[opParam])
210            node.Text = opParam.Name + ": " + opParam.ActualName;
211        }
212      }
213    }
214    private void operatorParameter_ValueChanged(object sender, EventArgs e) {
215      if (InvokeRequired)
216        Invoke(new EventHandler(operatorParameter_ValueChanged), sender, e);
217      else {
218        IOperatorParameter opParam = (IOperatorParameter)sender;
219        foreach (TreeNode node in operatorParameterNodeTable[opParam].ToArray())
220          ClearTreeNode(node);
221        foreach (TreeNode node in operatorParameterNodeTable[opParam]) {
222          node.Text = opParam.Name + ": ";
223          if (opParam.Value == null)
224            node.Text += opParam.ActualName;
225          else
226            FillTreeNode(node, opParam.Value);
227        }
228      }
229    }
230    private void op_NameChanged(object sender, EventArgs e) {
231      if (InvokeRequired)
232        Invoke(new EventHandler(op_NameChanged), sender, e);
233      else {
234        IOperator op = (IOperator)sender;
235        foreach (TreeNode node in operatorNodeTable[op]) {
236          IOperatorParameter opParam = GetOperatorParameterTag(node);
237          if (opParam == null)
238            node.Text = op.Name + " (" + op.ItemName + ")";
239          else
240            node.Text = opParam.Name + ": " + op.Name;
241        }
242      }
243    }
244    private void op_BreakpointChanged(object sender, EventArgs e) {
245      if (InvokeRequired)
246        Invoke(new EventHandler(op_BreakpointChanged), sender, e);
247      else {
248        IOperator op = (IOperator)sender;
249        foreach (TreeNode node in operatorNodeTable[op]) {
250          if (op.Breakpoint)
251            node.ForeColor = Color.Red;
252          else
253            node.ForeColor = graphTreeView.ForeColor;
254        }
255      }
256    }
257
258    private void Parameters_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
259      if (InvokeRequired)
260        Invoke(new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded), sender, e);
261      else {
262        IObservableKeyedCollection<string, IParameter> coll = (IObservableKeyedCollection<string, IParameter>)sender;
263        IOperator op = parametersOperatorTable[coll];
264        AddParameterNodes(op, e.Items);
265      }
266    }
267    private void Parameters_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
268      if (InvokeRequired)
269        Invoke(new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved), sender, e);
270      else
271        RemoveParameterNodes(e.Items);
272    }
273    private void Parameters_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
274      if (InvokeRequired)
275        Invoke(new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced), sender, e);
276      else {
277        RemoveParameterNodes(e.Items);
278        IObservableKeyedCollection<string, IParameter> coll = (IObservableKeyedCollection<string, IParameter>)sender;
279        IOperator op = parametersOperatorTable[coll];
280        AddParameterNodes(op, e.Items);
281      }
282    }
283    private void Parameters_CollectionReset(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
284      if (InvokeRequired)
285        Invoke(new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset), sender, e);
286      else {
287        RemoveParameterNodes(e.Items);
288        IObservableKeyedCollection<string, IParameter> coll = (IObservableKeyedCollection<string, IParameter>)sender;
289        IOperator op = parametersOperatorTable[coll];
290        AddParameterNodes(op, e.Items);
291      }
292    }
293    #endregion
294
295    #region TreeView Events
296    private void graphTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) {
297      TreeNode node = e.Node;
298      if ((node.Nodes.Count > 0) && (node.Nodes[0].Tag == null)) {
299        node.Nodes.Clear();
300        IOperator op = GetOperatorTag(node);
301        foreach (IParameter param in op.Parameters) {
302          IOperatorParameter opParam = param as IOperatorParameter;
303          if (opParam != null) node.Nodes.Add(CreateTreeNode(opParam));
304        }
305      }
306    }
307    private void graphTreeView_MouseDown(object sender, MouseEventArgs e) {
308      TreeNode node = graphTreeView.GetNodeAt(e.X, e.Y);
309      graphTreeView.SelectedNode = node;
310      graphTreeView.Refresh();
311    }
312    private void graphTreeView_KeyDown(object sender, KeyEventArgs e) {
313      if ((e.KeyCode == Keys.Delete) && (graphTreeView.SelectedNode != null)) {
314        IOperatorParameter opParam = GetOperatorParameterTag(graphTreeView.SelectedNode);
315        if (opParam != null) opParam.Value = null;
316      }
317    }
318    private void graphContextMenuStrip_Opening(object sender, CancelEventArgs e) {
319      viewToolStripMenuItem.Enabled = false;
320      breakpointToolStripMenuItem.Enabled = false;
321      breakpointToolStripMenuItem.Checked = false;
322      if (graphTreeView.SelectedNode != null) {
323        IOperator op = GetOperatorTag(graphTreeView.SelectedNode);
324        if (op != null) {
325          IView view = MainFormManager.CreateDefaultView(op);
326          if (view != null) {
327            viewToolStripMenuItem.Enabled = true;
328            viewToolStripMenuItem.Tag = view;
329          }
330          breakpointToolStripMenuItem.Enabled = true;
331          breakpointToolStripMenuItem.Tag = op;
332          if (op.Breakpoint)
333            breakpointToolStripMenuItem.Checked = true;
334        }
335      }
336    }
337    private void graphTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
338      TreeNode node = (TreeNode)e.Item;
339      IOperatorParameter opParam = GetOperatorParameterTag(node);
340      IOperator op = GetOperatorTag(node);
341      DataObject data = new DataObject();
342      data.SetData("Type", op.GetType());
343      data.SetData("Value", op);
344      if (opParam == null) {
345        DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
346      } else {
347        DragDropEffects action = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
348        if ((action & DragDropEffects.Move) == DragDropEffects.Move)
349          opParam.Value = null;
350      }
351    }
352    private void graphTreeView_DragEnterOver(object sender, DragEventArgs e) {
353      e.Effect = DragDropEffects.None;
354      Type type = e.Data.GetData("Type") as Type;
355      if ((type != null) && (typeof(IOperator).IsAssignableFrom(type))) {
356        TreeNode node = graphTreeView.GetNodeAt(graphTreeView.PointToClient(new Point(e.X, e.Y)));
357        if ((node != null) && (GetOperatorParameterTag(node) != null)) {
358          if ((e.KeyState & 8) == 8) e.Effect = DragDropEffects.Copy;  // CTRL key
359          else if ((e.KeyState & 32) == 32) e.Effect = DragDropEffects.Move;  // ALT key
360          else e.Effect = DragDropEffects.Link;
361        }
362      }
363    }
364    private void graphTreeView_DragDrop(object sender, DragEventArgs e) {
365      if (e.Effect != DragDropEffects.None) {
366        IOperator op = e.Data.GetData("Value") as IOperator;
367        if ((e.Effect & DragDropEffects.Copy) == DragDropEffects.Copy) op = (IOperator)op.Clone();
368        TreeNode node = graphTreeView.GetNodeAt(graphTreeView.PointToClient(new Point(e.X, e.Y)));
369        IOperatorParameter opParam = GetOperatorParameterTag(node);
370        opParam.Value = op;
371      }
372    }
373    #endregion
374
375    #region Context Menu Events
376    private void viewToolStripMenuItem_Click(object sender, EventArgs e) {
377      IView view = ((ToolStripMenuItem)sender).Tag as IView;
378      if (view != null) MainFormManager.MainForm.ShowView(view);
379    }
380    private void breakpointToolStripMenuItem_Click(object sender, EventArgs e) {
381      IOperator op = (IOperator)breakpointToolStripMenuItem.Tag;
382      op.Breakpoint = breakpointToolStripMenuItem.Checked;
383    }
384    #endregion
385
386    #region Helpers
387    private class Tuple<T1, T2> {
388      public T1 Item1 { get; set; }
389      public T2 Item2 { get; set; }
390
391      public Tuple() {
392        Item1 = default(T1);
393        Item2 = default(T2);
394      }
395      public Tuple(T1 item1, T2 item2) {
396        Item1 = item1;
397        Item2 = item2;
398      }
399    }
400
401    private IOperatorParameter GetOperatorParameterTag(TreeNode node) {
402      if (node.Tag != null)
403        return ((Tuple<IOperatorParameter, IOperator>)node.Tag).Item1;
404      else
405        return null;
406    }
407    private void SetOperatorParameterTag(TreeNode node, IOperatorParameter operatorParameter) {
408      if (node.Tag == null)
409        node.Tag = new Tuple<IOperatorParameter, IOperator>(operatorParameter, null);
410      else
411        ((Tuple<IOperatorParameter, IOperator>)node.Tag).Item1 = operatorParameter;
412    }
413    private IOperator GetOperatorTag(TreeNode node) {
414      if (node.Tag != null)
415        return ((Tuple<IOperatorParameter, IOperator>)node.Tag).Item2;
416      else
417        return null;
418    }
419    private void SetOperatorTag(TreeNode node, IOperator op) {
420      if (node.Tag == null)
421        node.Tag = new Tuple<IOperatorParameter, IOperator>(null, op);
422      else
423        ((Tuple<IOperatorParameter, IOperator>)node.Tag).Item2 = op;
424    }
425    #endregion
426  }
427}
Note: See TracBrowser for help on using the repository browser.