Free cookie consent management tool by TermsFeed Policy Generator

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

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

Changed items and views according to the refactoring of HeuristicLab.Collections (#977)

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