Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Persistence Test/HeuristicLab.Core/3.2/OperatorGraphView.cs @ 3591

Last change on this file since 3591 was 2474, checked in by swagner, 15 years ago

Implemented generic EventArgs (#796)

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