Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3566 was 3566, checked in by mkommend, 14 years ago

removed ctors with contents in all views (ticket #972)

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