Free cookie consent management tool by TermsFeed Policy Generator

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

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

Operator architecture refactoring (#95)

  • worked on parameters and operators
File size: 17.4 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 sealed partial class OperatorTreeView : ItemView {
40    private Dictionary<IValueParameter<IOperator>, List<TreeNode>> opParamNodeTable;
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 new IOperator Content {
50      get { return (IOperator)base.Content; }
51      set { base.Content = 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      opParamNodeTable = new Dictionary<IValueParameter<IOperator>, 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 content)
72      : this() {
73      Content = content;
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 OnContentChanged() {
81      base.OnContentChanged();
82      if (graphTreeView.Nodes.Count > 0)
83        RemoveTreeNode(graphTreeView.Nodes[0]);
84      graphTreeView.Enabled = false;
85      Caption = "Operator";
86      if (Content != null) {
87        Caption = Content.Name + " (" + Content.GetType().Name + ")";
88        TreeNode root = new TreeNode();
89        FillTreeNode(root, Content);
90        graphTreeView.Nodes.Add(root);
91        graphTreeView.Enabled = true;
92      }
93    }
94
95    #region TreeNode Management
96    private TreeNode CreateTreeNode(IValueParameter<IOperator> opParam) {
97      TreeNode node = new TreeNode();
98      node.Text = opParam.Name + ": ";
99      SetOperatorParameterTag(node, opParam);
100
101      if (!opParamNodeTable.ContainsKey(opParam)) {
102        opParamNodeTable.Add(opParam, new List<TreeNode>());
103        opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
104      }
105      opParamNodeTable[opParam].Add(node);
106
107      IOperator op = opParam.Value;
108      if (op == null)
109        node.Text += "-";
110      else
111        FillTreeNode(node, op);
112
113      return node;
114    }
115    private void FillTreeNode(TreeNode node, IOperator op) {
116      if (!graphTreeView.ImageList.Images.ContainsKey(op.GetType().FullName))
117        graphTreeView.ImageList.Images.Add(op.GetType().FullName, op.ItemImage);
118
119      node.Text += op.Name;
120      node.ToolTipText = op.ItemName + ": " + op.ItemDescription;
121      node.ImageIndex = graphTreeView.ImageList.Images.IndexOfKey(op.GetType().FullName);
122      node.SelectedImageIndex = node.ImageIndex;
123      SetOperatorTag(node, op);
124
125      if (!operatorNodeTable.ContainsKey(op)) {
126        operatorNodeTable.Add(op, new List<TreeNode>());
127        op.NameChanged += new EventHandler(op_NameChanged);
128        op.BreakpointChanged += new EventHandler(op_BreakpointChanged);
129        parametersOperatorTable.Add(op.Parameters, op);
130        op.Parameters.ItemsAdded += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
131        op.Parameters.ItemsRemoved += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
132        op.Parameters.ItemsReplaced += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
133        op.Parameters.CollectionReset += new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
134      }
135      operatorNodeTable[op].Add(node);
136
137      if (op.Breakpoint)
138        node.ForeColor = Color.Red;
139
140      foreach (IParameter param in op.Parameters) {
141        if (param is IValueParameter<IOperator>)
142          node.Nodes.Add(new TreeNode());
143      }
144      node.Collapse();
145    }
146    private void ClearTreeNode(TreeNode node) {
147      while (node.Nodes.Count > 0)
148        RemoveTreeNode(node.Nodes[0]);
149
150      IOperator op = GetOperatorTag(node);
151      if (op != null) {
152        operatorNodeTable[op].Remove(node);
153        if (operatorNodeTable[op].Count == 0) {
154          op.NameChanged -= new EventHandler(op_NameChanged);
155          op.BreakpointChanged -= new EventHandler(op_BreakpointChanged);
156          operatorNodeTable.Remove(op);
157          op.Parameters.ItemsAdded -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
158          op.Parameters.ItemsRemoved -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
159          op.Parameters.ItemsReplaced -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
160          op.Parameters.CollectionReset -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
161          parametersOperatorTable.Remove(op.Parameters);
162        }
163      }
164      SetOperatorTag(node, null);
165    }
166    private void RemoveTreeNode(TreeNode node) {
167      ClearTreeNode(node);
168
169      IValueParameter<IOperator> opParam = GetOperatorParameterTag(node);
170      if (opParam != null) {
171        opParamNodeTable[opParam].Remove(node);
172        if (opParamNodeTable[opParam].Count == 0) {
173          opParam.ValueChanged -= new EventHandler(opParam_ValueChanged);
174          opParamNodeTable.Remove(opParam);
175        }
176      }
177      SetOperatorParameterTag(node, null);
178      node.Remove();
179    }
180    private void AddParameterNodes(IOperator op, IEnumerable<IParameter> parameters) {
181      foreach (IParameter param in parameters) {
182        IValueParameter<IOperator> opParam = param as IValueParameter<IOperator>;
183        if (opParam != null) {
184          foreach (TreeNode node in operatorNodeTable[op])
185            node.Nodes.Add(CreateTreeNode(opParam));
186        }
187      }
188    }
189    private void RemoveParameterNodes(IEnumerable<IParameter> parameters) {
190      foreach (IParameter param in parameters) {
191        IValueParameter<IOperator> opParam = param as IValueParameter<IOperator>;
192        if (opParam != null) {
193          while (opParamNodeTable.ContainsKey(opParam))
194            RemoveTreeNode(opParamNodeTable[opParam][0]);
195        }
196      }
197    }
198    #endregion
199
200    #region Parameter and Operator Events
201    private void opParam_ValueChanged(object sender, EventArgs e) {
202      if (InvokeRequired)
203        Invoke(new EventHandler(opParam_ValueChanged), sender, e);
204      else {
205        IValueParameter<IOperator> opParam = (IValueParameter<IOperator>)sender;
206        foreach (TreeNode node in opParamNodeTable[opParam].ToArray())
207          ClearTreeNode(node);
208        foreach (TreeNode node in opParamNodeTable[opParam]) {
209          node.Text = opParam.Name + ": ";
210          if (opParam.Value == null)
211            node.Text += "-";
212          else
213            FillTreeNode(node, opParam.Value);
214        }
215      }
216    }
217    private void op_NameChanged(object sender, EventArgs e) {
218      if (InvokeRequired)
219        Invoke(new EventHandler(op_NameChanged), sender, e);
220      else {
221        IOperator op = (IOperator)sender;
222        foreach (TreeNode node in operatorNodeTable[op]) {
223          IValueParameter<IOperator> opParam = GetOperatorParameterTag(node);
224          if (opParam == null)
225            node.Text = op.Name + " (" + op.ItemName + ")";
226          else
227            node.Text = opParam.Name + ": " + op.Name;
228        }
229      }
230    }
231    private void op_BreakpointChanged(object sender, EventArgs e) {
232      if (InvokeRequired)
233        Invoke(new EventHandler(op_BreakpointChanged), sender, e);
234      else {
235        IOperator op = (IOperator)sender;
236        foreach (TreeNode node in operatorNodeTable[op]) {
237          if (op.Breakpoint)
238            node.ForeColor = Color.Red;
239          else
240            node.ForeColor = graphTreeView.ForeColor;
241        }
242      }
243    }
244
245    private void Parameters_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
246      if (InvokeRequired)
247        Invoke(new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded), sender, e);
248      else {
249        IObservableKeyedCollection<string, IParameter> coll = (IObservableKeyedCollection<string, IParameter>)sender;
250        IOperator op = parametersOperatorTable[coll];
251        AddParameterNodes(op, e.Items);
252      }
253    }
254    private void Parameters_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
255      if (InvokeRequired)
256        Invoke(new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved), sender, e);
257      else
258        RemoveParameterNodes(e.Items);
259    }
260    private void Parameters_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
261      if (InvokeRequired)
262        Invoke(new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced), sender, e);
263      else {
264        RemoveParameterNodes(e.Items);
265        IObservableKeyedCollection<string, IParameter> coll = (IObservableKeyedCollection<string, IParameter>)sender;
266        IOperator op = parametersOperatorTable[coll];
267        AddParameterNodes(op, e.Items);
268      }
269    }
270    private void Parameters_CollectionReset(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
271      if (InvokeRequired)
272        Invoke(new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset), sender, e);
273      else {
274        RemoveParameterNodes(e.Items);
275        IObservableKeyedCollection<string, IParameter> coll = (IObservableKeyedCollection<string, IParameter>)sender;
276        IOperator op = parametersOperatorTable[coll];
277        AddParameterNodes(op, e.Items);
278      }
279    }
280    #endregion
281
282    #region TreeView Events
283    private void graphTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) {
284      TreeNode node = e.Node;
285      if ((node.Nodes.Count > 0) && (node.Nodes[0].Tag == null)) {
286        node.Nodes.Clear();
287        IOperator op = GetOperatorTag(node);
288        foreach (IParameter param in op.Parameters) {
289          IValueParameter<IOperator> opParam = param as IValueParameter<IOperator>;
290          if (opParam != null) node.Nodes.Add(CreateTreeNode(opParam));
291        }
292      }
293    }
294    private void graphTreeView_MouseDown(object sender, MouseEventArgs e) {
295      TreeNode node = graphTreeView.GetNodeAt(e.X, e.Y);
296      graphTreeView.SelectedNode = node;
297      graphTreeView.Refresh();
298    }
299    private void graphTreeView_KeyDown(object sender, KeyEventArgs e) {
300      if ((e.KeyCode == Keys.Delete) && (graphTreeView.SelectedNode != null)) {
301        IValueParameter<IOperator> opParam = GetOperatorParameterTag(graphTreeView.SelectedNode);
302        if (opParam != null) opParam.Value = null;
303      }
304    }
305    private void graphContextMenuStrip_Opening(object sender, CancelEventArgs e) {
306      viewToolStripMenuItem.Enabled = false;
307      breakpointToolStripMenuItem.Enabled = false;
308      breakpointToolStripMenuItem.Checked = false;
309      if (graphTreeView.SelectedNode != null) {
310        IOperator op = GetOperatorTag(graphTreeView.SelectedNode);
311        if (op != null) {
312          IView view = MainFormManager.CreateDefaultView(op);
313          if (view != null) {
314            viewToolStripMenuItem.Enabled = true;
315            viewToolStripMenuItem.Tag = view;
316          }
317          breakpointToolStripMenuItem.Enabled = true;
318          breakpointToolStripMenuItem.Tag = op;
319          if (op.Breakpoint)
320            breakpointToolStripMenuItem.Checked = true;
321        }
322      }
323    }
324    private void graphTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
325      TreeNode node = (TreeNode)e.Item;
326      IValueParameter<IOperator> opParam = GetOperatorParameterTag(node);
327      IOperator op = GetOperatorTag(node);
328      DataObject data = new DataObject();
329      data.SetData("Type", op.GetType());
330      data.SetData("Value", op);
331      if (opParam == null) {
332        DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
333      } else {
334        DragDropEffects action = DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move);
335        if ((action & DragDropEffects.Move) == DragDropEffects.Move)
336          opParam.Value = null;
337      }
338    }
339    private void graphTreeView_DragEnterOver(object sender, DragEventArgs e) {
340      e.Effect = DragDropEffects.None;
341      Type type = e.Data.GetData("Type") as Type;
342      if ((type != null) && (typeof(IOperator).IsAssignableFrom(type))) {
343        TreeNode node = graphTreeView.GetNodeAt(graphTreeView.PointToClient(new Point(e.X, e.Y)));
344        if ((node != null) && !node.IsExpanded) node.Expand();
345        if ((node != null) && (GetOperatorParameterTag(node) != null)) {
346          if ((e.KeyState & 8) == 8) e.Effect = DragDropEffects.Copy;  // CTRL key
347          else if ((e.KeyState & 4) == 4) e.Effect = DragDropEffects.Move;  // SHIFT key
348          else if ((e.AllowedEffect & DragDropEffects.Link) == DragDropEffects.Link) e.Effect = DragDropEffects.Link;
349          else if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy;
350          else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) e.Effect = DragDropEffects.Move;
351        }
352      }
353    }
354    private void graphTreeView_DragDrop(object sender, DragEventArgs e) {
355      if (e.Effect != DragDropEffects.None) {
356        IOperator op = e.Data.GetData("Value") as IOperator;
357        if ((e.Effect & DragDropEffects.Copy) == DragDropEffects.Copy) op = (IOperator)op.Clone();
358        TreeNode node = graphTreeView.GetNodeAt(graphTreeView.PointToClient(new Point(e.X, e.Y)));
359        IValueParameter<IOperator> opParam = GetOperatorParameterTag(node);
360        opParam.Value = op;
361      }
362    }
363    #endregion
364
365    #region Context Menu Events
366    private void viewToolStripMenuItem_Click(object sender, EventArgs e) {
367      IView view = ((ToolStripMenuItem)sender).Tag as IView;
368      if (view != null) view.Show();
369    }
370    private void breakpointToolStripMenuItem_Click(object sender, EventArgs e) {
371      IOperator op = (IOperator)breakpointToolStripMenuItem.Tag;
372      op.Breakpoint = breakpointToolStripMenuItem.Checked;
373    }
374    #endregion
375
376    #region Helpers
377    private class Tuple<T1, T2> {
378      public T1 Item1 { get; set; }
379      public T2 Item2 { get; set; }
380
381      public Tuple() {
382        Item1 = default(T1);
383        Item2 = default(T2);
384      }
385      public Tuple(T1 item1, T2 item2) {
386        Item1 = item1;
387        Item2 = item2;
388      }
389    }
390
391    private IValueParameter<IOperator> GetOperatorParameterTag(TreeNode node) {
392      if (node.Tag != null)
393        return ((Tuple<IValueParameter<IOperator>, IOperator>)node.Tag).Item1;
394      else
395        return null;
396    }
397    private void SetOperatorParameterTag(TreeNode node, IValueParameter<IOperator> opParam) {
398      if (node.Tag == null)
399        node.Tag = new Tuple<IValueParameter<IOperator>, IOperator>(opParam, null);
400      else
401        ((Tuple<IValueParameter<IOperator>, IOperator>)node.Tag).Item1 = opParam;
402    }
403    private IOperator GetOperatorTag(TreeNode node) {
404      if (node.Tag != null)
405        return ((Tuple<IValueParameter<IOperator>, IOperator>)node.Tag).Item2;
406      else
407        return null;
408    }
409    private void SetOperatorTag(TreeNode node, IOperator op) {
410      if (node.Tag == null)
411        node.Tag = new Tuple<IValueParameter<IOperator>, IOperator>(null, op);
412      else
413        ((Tuple<IValueParameter<IOperator>, IOperator>)node.Tag).Item2 = op;
414    }
415    #endregion
416  }
417}
Note: See TracBrowser for help on using the repository browser.