Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 2655 was 2655, checked in by swagner, 14 years ago

Committing first results of the refactoring of HeuristicLab.Core and related plugins (#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 : ItemViewBase {
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.