Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3105 was 3105, checked in by abeham, 14 years ago

I added a default icon to the imageList in the constructor #927

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