Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core/OperatorGraphView.cs @ 1196

Last change on this file since 1196 was 776, checked in by vdorfer, 16 years ago

Created API documentation for HeuristicLab.Core namespace (#331)

File size: 21.3 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;
30
31namespace HeuristicLab.Core {
32  /// <summary>
33  /// The visual representation of an <see cref="IOperatorGraph"/>.
34  /// </summary>
35  public partial class OperatorGraphView : ViewBase {
36    private ChooseOperatorDialog chooseOperatorDialog;
37    private Dictionary<IOperator, IList<TreeNode>> operatorNodeTable;
38
39    /// <summary>
40    /// Gets or sets the operator graph to represent visually.
41    /// </summary>
42    /// <remarks>Uses property <see cref="ViewBase.Item"/> of base class <see cref="ViewBase"/>.
43    /// No own data storage present.</remarks>
44    public IOperatorGraph OperatorGraph {
45      get { return (IOperatorGraph)Item; }
46      set { base.Item = value; }
47    }
48
49    /// <summary>
50    /// Initializes a new instance of <see cref="OperatorGraphView"/> with caption "Operator Graph".
51    /// </summary>
52    public OperatorGraphView() {
53      InitializeComponent();
54      operatorNodeTable = new Dictionary<IOperator, IList<TreeNode>>();
55      operatorsListView.Columns[0].Width = Math.Max(0, operatorsListView.Width - 25);
56      Caption = "Operator Graph";
57    }
58    /// <summary>
59    /// Initializes a new instance of <see cref="OperatorGraphView"/>
60    /// with the given <paramref name="operatorGraph"/>.
61    /// </summary>
62    /// <remarks>Calls <see cref="OperatorGraphView()"/>.</remarks>
63    /// <param name="operatorGraph">The operator graph to represent visually.</param>
64    public OperatorGraphView(IOperatorGraph operatorGraph)
65      : this() {
66      OperatorGraph = operatorGraph;
67    }
68
69    /// <summary>
70    /// Removes the eventhandlers from the underlying <see cref="IOperatorGraph"/>.
71    /// </summary>
72    /// <remarks>Calls <see cref="ViewBase.RemoveItemEvents"/> of base class <see cref="ViewBase"/>.</remarks>
73    protected override void RemoveItemEvents() {
74      OperatorGraph.OperatorAdded -= new EventHandler<OperatorEventArgs>(OperatorGraph_OperatorAdded);
75      OperatorGraph.OperatorRemoved -= new EventHandler<OperatorEventArgs>(OperatorGraph_OperatorRemoved);
76      OperatorGraph.InitialOperatorChanged -= new EventHandler(OperatorGraph_InitialOperatorChanged);
77      base.RemoveItemEvents();
78    }
79    /// <summary>
80    /// Adds eventhandlers to the underlying <see cref="IOperatorGraph"/>.
81    /// </summary>
82    /// <remarks>Calls <see cref="ViewBase.AddItemEvents"/> of base class <see cref="ViewBase"/>.</remarks>
83    protected override void AddItemEvents() {
84      base.AddItemEvents();
85      OperatorGraph.OperatorAdded += new EventHandler<OperatorEventArgs>(OperatorGraph_OperatorAdded);
86      OperatorGraph.OperatorRemoved += new EventHandler<OperatorEventArgs>(OperatorGraph_OperatorRemoved);
87      OperatorGraph.InitialOperatorChanged += new EventHandler(OperatorGraph_InitialOperatorChanged);
88    }
89
90    /// <summary>
91    /// Updates all controls with the latest data of the model.
92    /// </summary>
93    /// <remarks>Calls <see cref="ViewBase.UpdateControls"/> of base class <see cref="ViewBase"/>.</remarks>
94    protected override void UpdateControls() {
95      base.UpdateControls();
96      if (graphTreeView.Nodes.Count > 0)
97        RemoveTreeNode(graphTreeView.Nodes[0]);
98      graphTreeView.SelectedNode = null;
99      graphTreeView.Nodes.Clear();
100      graphTreeView.Enabled = false;
101      operatorsListView.Items.Clear();
102      removeButton.Enabled = false;
103      if (OperatorGraph == null) {
104        Caption = "Operator Graph";
105        operatorsListView.Enabled = false;
106        addOperatorButton.Enabled = false;
107      } else {
108        Caption = "Operator Graph (" + OperatorGraph.GetType().Name + ")";
109        foreach (IOperator op in OperatorGraph.Operators) {
110          operatorsListView.Items.Add(CreateListViewItem(op));
111        }
112        operatorsListView.Enabled = true;
113        addOperatorButton.Enabled = true;
114        if (OperatorGraph.InitialOperator != null) {
115          graphTreeView.Nodes.Add(CreateTreeNode(OperatorGraph.InitialOperator));
116          graphTreeView.Enabled = true;
117        }
118      }
119    }
120
121    private ListViewItem CreateListViewItem(IOperator op) {
122      ListViewItem item = new ListViewItem();
123      item.Text = op.Name;
124      item.Tag = op;
125      item.ImageIndex = 0;
126      if (op.GetType().Name == "CombinedOperator")
127        item.ImageIndex = 1;
128      else if (op.GetType().Name == "ProgrammableOperator")
129        item.ImageIndex = 2;
130      if (op == OperatorGraph.InitialOperator)
131        item.Font = new Font(operatorsListView.Font, FontStyle.Bold);
132      return item;
133    }
134
135    private TreeNode CreateTreeNode(IOperator op) {
136      TreeNode node = new TreeNode();
137      node.Text = op.Name;
138      node.Tag = op;
139      if (op.Breakpoint)
140        node.ForeColor = Color.Red;
141
142      if (!operatorNodeTable.ContainsKey(op)) {
143        operatorNodeTable.Add(op, new List<TreeNode>());
144        op.NameChanged += new EventHandler(Operator_NameChanged);
145        op.BreakpointChanged += new EventHandler(Operator_BreakpointChanged);
146        op.SubOperatorAdded += new EventHandler<OperatorIndexEventArgs>(Operator_SubOperatorAdded);
147        op.SubOperatorRemoved += new EventHandler<OperatorIndexEventArgs>(Operator_SubOperatorRemoved);
148      }
149      operatorNodeTable[op].Add(node);
150
151      for (int i = 0; i < op.SubOperators.Count; i++)
152        node.Nodes.Add(new TreeNode());
153      return node;
154    }
155
156    private void RemoveTreeNode(TreeNode node) {
157      foreach (TreeNode child in node.Nodes)
158        RemoveTreeNode(child);
159
160      IOperator op = (IOperator)node.Tag;
161      if (op != null) {
162        operatorNodeTable[op].Remove(node);
163        if (operatorNodeTable[op].Count == 0) {
164          op.NameChanged -= new EventHandler(Operator_NameChanged);
165          op.BreakpointChanged -= new EventHandler(Operator_BreakpointChanged);
166          op.SubOperatorAdded -= new EventHandler<OperatorIndexEventArgs>(Operator_SubOperatorAdded);
167          op.SubOperatorRemoved -= new EventHandler<OperatorIndexEventArgs>(Operator_SubOperatorRemoved);
168          operatorNodeTable.Remove(op);
169        }
170      }
171    }
172
173    #region ListView Events
174    private void operatorsListView_SelectedIndexChanged(object sender, EventArgs e) {
175      removeButton.Enabled = false;
176      if (operatorsListView.SelectedItems.Count > 0) {
177        removeButton.Enabled = true;
178      }
179    }
180    private void operatorsListView_DoubleClick(object sender, EventArgs e) {
181      if (operatorsListView.SelectedItems.Count == 1) {
182        IOperator op = (IOperator)operatorsListView.SelectedItems[0].Tag;
183        IView view = op.CreateView();
184        if (view != null)
185          PluginManager.ControlManager.ShowControl(view);
186      }
187    }
188    #endregion
189
190    #region TreeView Events
191    private void graphTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) {
192      TreeNode node = e.Node;
193      IOperator op = (IOperator)node.Tag;
194      for (int i = 0; i < node.Nodes.Count; i++) {
195        if (node.Nodes[i].Tag == null) {
196          node.Nodes[i].Remove();
197          node.Nodes.Insert(i, CreateTreeNode(op.SubOperators[i]));
198        }
199      }
200    }
201    private void graphTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
202      IOperator op = (IOperator)e.Node.Tag;
203      foreach (ListViewItem item in operatorsListView.Items)
204        item.Selected = item.Tag == op;
205    }
206    #endregion
207
208    #region Size Changed Events
209    private void operatorsListView_SizeChanged(object sender, EventArgs e) {
210      if (operatorsListView.Columns.Count > 0)
211        operatorsListView.Columns[0].Width = Math.Max(0, operatorsListView.Width - 25);
212    }
213    #endregion
214
215    #region Key Events
216    private void operatorsListView_KeyDown(object sender, KeyEventArgs e) {
217      if (e.KeyCode == Keys.Delete) {
218        if (operatorsListView.SelectedItems.Count > 0) {
219          foreach (ListViewItem item in operatorsListView.SelectedItems)
220            OperatorGraph.RemoveOperator(((IOperator)item.Tag).Guid);
221        }
222      }
223      if (e.KeyCode == Keys.F2) {
224        if (operatorsListView.SelectedItems.Count == 1)
225          operatorsListView.SelectedItems[0].BeginEdit();
226      }
227    }
228    private void graphTreeView_KeyDown(object sender, KeyEventArgs e) {
229      if (e.KeyCode == Keys.Delete) {
230        TreeNode node = graphTreeView.SelectedNode;
231        if ((node != null) && (node.Parent != null)) {
232          IOperator parent = (IOperator)node.Parent.Tag;
233          parent.RemoveSubOperator(node.Index);
234        }
235      }
236    }
237    #endregion
238
239    #region Edit Events
240    private void operatorsListView_AfterLabelEdit(object sender, LabelEditEventArgs e) {
241      e.CancelEdit = false;
242
243      string name = e.Label;
244      if (name != null) {
245        IOperator op = (IOperator)operatorsListView.Items[e.Item].Tag;
246        op.Name = name;
247      }
248    }
249    #endregion
250
251    #region Button Events
252    private void addOperatorButton_Click(object sender, EventArgs e) {
253      if (chooseOperatorDialog == null) chooseOperatorDialog = new ChooseOperatorDialog();
254      if (chooseOperatorDialog.ShowDialog(this) == DialogResult.OK)
255        OperatorGraph.AddOperator(chooseOperatorDialog.Operator);
256    }
257    private void removeButton_Click(object sender, EventArgs e) {
258      if (operatorsListView.SelectedItems.Count > 0) {
259        foreach (ListViewItem item in operatorsListView.SelectedItems)
260          OperatorGraph.RemoveOperator(((IOperator)item.Tag).Guid);
261      }
262    }
263    #endregion
264
265    #region Drag and Drop Events
266    private void operatorsListView_ItemDrag(object sender, ItemDragEventArgs e) {
267      ListViewItem item = (ListViewItem)e.Item;
268      IOperator op = (IOperator)item.Tag;
269      DataObject data = new DataObject();
270      data.SetData("IOperator", op);
271      data.SetData("DragSource", operatorsListView);
272      DoDragDrop(data, DragDropEffects.Copy);
273    }
274    private void operatorsListView_DragEnter(object sender, DragEventArgs e) {
275      e.Effect = DragDropEffects.None;
276      if (e.Data.GetDataPresent("IOperator"))
277        e.Effect = DragDropEffects.Copy;
278    }
279    private void operatorsListView_DragOver(object sender, DragEventArgs e) {
280      e.Effect = DragDropEffects.None;
281      if (e.Data.GetDataPresent("IOperator"))
282        e.Effect = DragDropEffects.Copy;
283    }
284    private void operatorsListView_DragDrop(object sender, DragEventArgs e) {
285      if (e.Effect != DragDropEffects.None) {
286        if (e.Data.GetDataPresent("IOperator")) {
287          IOperator op = (IOperator)e.Data.GetData("IOperator");
288          op = (IOperator)op.Clone();
289          OperatorGraph.AddOperator(op);
290        }
291      }
292    }
293    private void graphTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
294      TreeNode node = (TreeNode)e.Item;
295      if (node.Parent != null) {
296        IOperator op = (IOperator)node.Tag;
297        IOperator parent = (IOperator)node.Parent.Tag;
298        int index = node.Index;
299        DataObject data = new DataObject();
300        data.SetData("IOperator", op);
301        data.SetData("DragSource", graphTreeView);
302        data.SetData("ParentOperator", parent);
303        data.SetData("Index", index);
304        DoDragDrop(data, DragDropEffects.Move);
305      }
306    }
307    private void graphTreeView_DragEnter(object sender, DragEventArgs e) {
308      e.Effect = DragDropEffects.None;
309      if (e.Data.GetDataPresent("IOperator")) {
310        Point p = graphTreeView.PointToClient(new Point(e.X, e.Y));
311        TreeNode node = graphTreeView.GetNodeAt(p);
312        if (node != null) {
313          if ((e.Data.GetDataPresent("ParentOperator")) && (node.Parent != null)) {
314            if ((e.Data.GetDataPresent("DragSource")) && (e.Data.GetData("DragSource") == graphTreeView))
315              e.Effect = DragDropEffects.Move;
316          } else {
317            if ((e.Data.GetDataPresent("DragSource")) && (e.Data.GetData("DragSource") == operatorsListView))
318              e.Effect = DragDropEffects.Copy;
319          }
320        }
321      }
322    }
323    private void graphTreeView_DragOver(object sender, DragEventArgs e) {
324      e.Effect = DragDropEffects.None;
325      if (e.Data.GetDataPresent("IOperator")) {
326        Point p = graphTreeView.PointToClient(new Point(e.X, e.Y));
327        TreeNode node = graphTreeView.GetNodeAt(p);
328        if (node != null) {
329          if ((e.Data.GetDataPresent("ParentOperator")) && (node.Parent != null)) {
330            if ((e.Data.GetDataPresent("DragSource")) && (e.Data.GetData("DragSource") == graphTreeView))
331              e.Effect = DragDropEffects.Move;
332          } else {
333            if ((e.Data.GetDataPresent("DragSource")) && (e.Data.GetData("DragSource") == operatorsListView))
334              e.Effect = DragDropEffects.Copy;
335          }
336        }
337      }
338    }
339    private void graphTreeView_DragDrop(object sender, DragEventArgs e) {
340      if (e.Effect != DragDropEffects.None) {
341        if (e.Data.GetDataPresent("IOperator")) {
342          IOperator op = (IOperator)e.Data.GetData("IOperator");
343          Point p = graphTreeView.PointToClient(new Point(e.X, e.Y));
344          TreeNode node = graphTreeView.GetNodeAt(p);
345          if (e.Data.GetDataPresent("ParentOperator")) {
346            if (node.Parent != null) {
347              TreeNode parentNode = node.Parent;
348              IOperator oldParent = (IOperator)e.Data.GetData("ParentOperator");
349              int oldIndex = (int)e.Data.GetData("Index");
350              IOperator newParent = (IOperator)node.Parent.Tag;
351              int newIndex = node.Index;
352              ICollection<IConstraint> violatedConstraints;
353              ICollection<IConstraint> violatedConstraints2;
354              oldParent.TryRemoveSubOperator(oldIndex, out violatedConstraints);
355              newParent.TryAddSubOperator(op, newIndex, out violatedConstraints2);
356              if ((violatedConstraints.Count == 0) && (violatedConstraints2.Count == 0)) {
357                graphTreeView.SelectedNode = parentNode.Nodes[newIndex];
358              } else {
359                List<IConstraint> allViolatedConstraints = new List<IConstraint>(violatedConstraints);
360                allViolatedConstraints.AddRange(violatedConstraints2);
361                if (Auxiliary.ShowIgnoreConstraintViolationMessageBox(allViolatedConstraints) == DialogResult.Yes) {
362                  if (violatedConstraints.Count > 0)
363                    oldParent.RemoveSubOperator(oldIndex);
364                  if (violatedConstraints2.Count > 0)
365                    newParent.AddSubOperator(op, newIndex);
366                  graphTreeView.SelectedNode = parentNode.Nodes[newIndex];
367                } else {
368                  if (violatedConstraints.Count == 0)
369                    oldParent.AddSubOperator(op, oldIndex);
370                  if (violatedConstraints2.Count == 0)
371                    newParent.RemoveSubOperator(newIndex);
372                }
373              }
374            }
375          } else {
376            if (node != null) {
377              IOperator parent = (IOperator)node.Tag;
378              ICollection<IConstraint> violatedConstraints;
379              if (parent.TryAddSubOperator(op, out violatedConstraints)) {
380                graphTreeView.SelectedNode = node.Nodes[node.Nodes.Count - 1];
381              } else if (Auxiliary.ShowIgnoreConstraintViolationMessageBox(violatedConstraints) == DialogResult.Yes) {
382                parent.AddSubOperator(op);
383                graphTreeView.SelectedNode = node.Nodes[node.Nodes.Count - 1];
384              }
385            }
386          }
387        }
388      }
389    }
390    #endregion
391
392    #region Context Menu Events
393    private void operatorsContextMenuStrip_Opening(object sender, CancelEventArgs e) {
394      viewToolStripMenuItem.Enabled = false;
395      initialOperatorToolStripMenuItem.Enabled = false;
396      initialOperatorToolStripMenuItem.Checked = false;
397      if (operatorsListView.SelectedItems.Count == 1) {
398        IOperator op = (IOperator)operatorsListView.SelectedItems[0].Tag;
399        IView view = op.CreateView();
400        if (view != null) {
401          viewToolStripMenuItem.Enabled = true;
402          viewToolStripMenuItem.Tag = view;
403        }
404        initialOperatorToolStripMenuItem.Enabled = true;
405        initialOperatorToolStripMenuItem.Tag = op;
406        if (op == OperatorGraph.InitialOperator)
407          initialOperatorToolStripMenuItem.Checked = true;
408      }
409    }
410    private void viewToolStripMenuItem_Click(object sender, EventArgs e) {
411      IView view = (IView)((ToolStripMenuItem)sender).Tag;
412      PluginManager.ControlManager.ShowControl(view);
413    }
414    private void initialOperatorToolStripMenuItem_Click(object sender, EventArgs e) {
415      if (initialOperatorToolStripMenuItem.Checked) {
416        foreach (ListViewItem item in operatorsListView.Items)
417          item.Font = operatorsListView.Font;
418        operatorsListView.SelectedItems[0].Font = new Font(operatorsListView.Font, FontStyle.Bold);
419        OperatorGraph.InitialOperator = (IOperator)initialOperatorToolStripMenuItem.Tag;
420      } else {
421        operatorsListView.SelectedItems[0].Font = operatorsListView.Font;
422        OperatorGraph.InitialOperator = null;
423      }
424    }
425    private void graphContextMenuStrip_Opening(object sender, CancelEventArgs e) {
426      viewToolStripMenuItem1.Enabled = false;
427      breakpointToolStripMenuItem.Enabled = false;
428      breakpointToolStripMenuItem.Checked = false;
429      if (graphTreeView.SelectedNode != null) {
430        IOperator op = (IOperator)graphTreeView.SelectedNode.Tag;
431        IView view = op.CreateView();
432        if (view != null) {
433          viewToolStripMenuItem1.Enabled = true;
434          viewToolStripMenuItem1.Tag = view;
435        }
436        breakpointToolStripMenuItem.Enabled = true;
437        breakpointToolStripMenuItem.Tag = op;
438        if (op.Breakpoint)
439          breakpointToolStripMenuItem.Checked = true;
440      }
441    }
442    private void breakpointToolStripMenuItem_Click(object sender, EventArgs e) {
443      IOperator op = (IOperator)breakpointToolStripMenuItem.Tag;
444      op.Breakpoint = breakpointToolStripMenuItem.Checked;
445    }
446    #endregion
447
448    #region OperatorGraph Events
449    private void OperatorGraph_OperatorAdded(object sender, OperatorEventArgs e) {
450      operatorsListView.Items.Add(CreateListViewItem(e.Operator));
451    }
452    private void OperatorGraph_OperatorRemoved(object sender, OperatorEventArgs e) {
453      ListViewItem itemToDelete = null;
454      foreach (ListViewItem item in operatorsListView.Items) {
455        if (item.Tag == e.Operator)
456          itemToDelete = item;
457      }
458      itemToDelete.Remove();
459    }
460    private void OperatorGraph_InitialOperatorChanged(object sender, EventArgs e) {
461      Refresh();
462    }
463    #endregion
464
465    #region Operator Events
466    private void Operator_NameChanged(object sender, EventArgs e) {
467      IOperator op = (IOperator)sender;
468      foreach (TreeNode node in operatorNodeTable[op])
469        node.Text = op.Name;
470    }
471    private void Operator_BreakpointChanged(object sender, EventArgs e) {
472      IOperator op = (IOperator)sender;
473      foreach (TreeNode node in operatorNodeTable[op]) {
474        if (op.Breakpoint)
475          node.ForeColor = Color.Red;
476        else
477          node.ForeColor = graphTreeView.ForeColor;
478      }
479    }
480    private void Operator_SubOperatorAdded(object sender, OperatorIndexEventArgs e) {
481      IOperator op = (IOperator)sender;
482      if (operatorNodeTable.ContainsKey(op)) {
483        TreeNode[] nodes = new TreeNode[operatorNodeTable[op].Count];
484        operatorNodeTable[op].CopyTo(nodes, 0);
485        foreach (TreeNode node in nodes)
486          node.Nodes.Insert(e.Index, CreateTreeNode(e.Operator));
487      }
488    }
489    private void Operator_SubOperatorRemoved(object sender, OperatorIndexEventArgs e) {
490      IOperator op = (IOperator)sender;
491      if (operatorNodeTable.ContainsKey(op)) {
492        TreeNode[] nodes = new TreeNode[operatorNodeTable[op].Count];
493        operatorNodeTable[op].CopyTo(nodes, 0);
494        foreach (TreeNode node in nodes) {
495          RemoveTreeNode(node.Nodes[e.Index]);
496          node.Nodes.RemoveAt(e.Index);
497        }
498      }
499    }
500    #endregion
501
502    #region Mouse Events
503    private void graphTreeView_MouseDown(object sender, MouseEventArgs e) {
504      if (e.Button != MouseButtons.Right) return;
505      TreeNode clickedNode = graphTreeView.GetNodeAt(e.X, e.Y);
506      if (clickedNode != null) {
507        graphTreeView.SelectedNode = clickedNode;
508        graphTreeView.Refresh();
509      }
510    }
511    #endregion
512
513  }
514}
Note: See TracBrowser for help on using the repository browser.